summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-25 19:09:13 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-25 19:09:13 +0000
commit4e55071879aae604b7b61c93dc815a357571cd88 (patch)
tree4be73b1dfa1bf0df8368023010f530954ed3ff7c /src
parenta1c93c13ae14bf12110f9a5d5813a22668d69bfe (diff)
downloadvyos-strongswan-4e55071879aae604b7b61c93dc815a357571cd88.tar.gz
vyos-strongswan-4e55071879aae604b7b61c93dc815a357571cd88.zip
New upstream release.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.in36
-rw-r--r--src/_copyright/Makefile.in1
-rw-r--r--src/_updown/Makefile.in1
-rw-r--r--src/_updown_espmark/Makefile.in1
-rw-r--r--src/charon/Android.mk27
-rw-r--r--src/charon/Makefile.am281
-rw-r--r--src/charon/Makefile.in2158
-rw-r--r--src/charon/charon.c417
-rw-r--r--src/checksum/Makefile.am17
-rw-r--r--src/checksum/Makefile.in30
-rw-r--r--src/checksum/checksum_builder.c29
-rw-r--r--src/dumm/Makefile.in1
-rw-r--r--src/dumm/bridge.c22
-rw-r--r--src/dumm/cowfs.c16
-rw-r--r--src/dumm/dumm.c11
-rw-r--r--src/dumm/guest.c20
-rw-r--r--src/dumm/iface.c14
-rw-r--r--src/dumm/mconsole.c22
-rw-r--r--src/include/Makefile.am2
-rw-r--r--src/include/Makefile.in3
-rw-r--r--src/include/linux/jhash.h143
-rw-r--r--src/include/linux/pfkeyv2.h1
-rw-r--r--src/ipsec/Makefile.in1
-rwxr-xr-xsrc/ipsec/ipsec.in31
-rw-r--r--src/libcharon/Android.mk174
-rw-r--r--src/libcharon/Makefile.am418
-rw-r--r--src/libcharon/Makefile.in1994
-rw-r--r--src/libcharon/bus/bus.c727
-rw-r--r--src/libcharon/bus/bus.h286
-rw-r--r--src/libcharon/bus/listeners/file_logger.c125
-rw-r--r--src/libcharon/bus/listeners/file_logger.h60
-rw-r--r--src/libcharon/bus/listeners/listener.h178
-rw-r--r--src/libcharon/bus/listeners/sys_logger.c121
-rw-r--r--src/libcharon/bus/listeners/sys_logger.h62
-rw-r--r--src/libcharon/config/auth_cfg.c768
-rw-r--r--src/libcharon/config/auth_cfg.h201
-rw-r--r--src/libcharon/config/backend.h83
-rw-r--r--src/libcharon/config/backend_manager.c444
-rw-r--r--src/libcharon/config/backend_manager.h114
-rw-r--r--src/libcharon/config/child_cfg.c552
-rw-r--r--src/libcharon/config/child_cfg.h310
-rw-r--r--src/libcharon/config/ike_cfg.c294
-rw-r--r--src/libcharon/config/ike_cfg.h161
-rw-r--r--src/libcharon/config/peer_cfg.c699
-rw-r--r--src/libcharon/config/peer_cfg.h358
-rw-r--r--src/libcharon/config/proposal.c949
-rw-r--r--src/libcharon/config/proposal.h226
-rw-r--r--src/libcharon/control/controller.c455
-rw-r--r--src/libcharon/control/controller.h140
-rw-r--r--src/libcharon/credentials/credential_manager.c1681
-rw-r--r--src/libcharon/credentials/credential_manager.h203
-rw-r--r--src/libcharon/credentials/credential_set.h108
-rw-r--r--src/libcharon/credentials/sets/auth_cfg_wrapper.c223
-rw-r--r--src/libcharon/credentials/sets/auth_cfg_wrapper.h53
-rw-r--r--src/libcharon/credentials/sets/cert_cache.c390
-rw-r--r--src/libcharon/credentials/sets/cert_cache.h71
-rw-r--r--src/libcharon/credentials/sets/ocsp_response_wrapper.c147
-rw-r--r--src/libcharon/credentials/sets/ocsp_response_wrapper.h53
-rw-r--r--src/libcharon/daemon.c443
-rw-r--r--src/libcharon/daemon.h341
-rw-r--r--src/libcharon/encoding/generator.c888
-rw-r--r--src/libcharon/encoding/generator.h85
-rw-r--r--src/libcharon/encoding/message.c1723
-rw-r--r--src/libcharon/encoding/message.h359
-rw-r--r--src/libcharon/encoding/parser.c862
-rw-r--r--src/libcharon/encoding/parser.h79
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.c259
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.h102
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.c340
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.h137
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c298
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.h90
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.c264
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.h85
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.c273
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.h108
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c292
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.h84
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.c302
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.h129
-rw-r--r--src/libcharon/encoding/payloads/encodings.c58
-rw-r--r--src/libcharon/encoding/payloads/encodings.h515
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.c619
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.h173
-rw-r--r--src/libcharon/encoding/payloads/endpoint_notify.c422
-rw-r--r--src/libcharon/encoding/payloads/endpoint_notify.h173
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c293
-rw-r--r--src/libcharon/encoding/payloads/id_payload.h122
-rw-r--r--src/libcharon/encoding/payloads/ike_header.c415
-rw-r--r--src/libcharon/encoding/payloads/ike_header.h227
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c270
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.h104
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.c225
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.h78
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c617
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.h232
-rw-r--r--src/libcharon/encoding/payloads/payload.c184
-rw-r--r--src/libcharon/encoding/payloads/payload.h272
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c598
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.h173
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c368
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.h115
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.c276
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.h151
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c325
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.h132
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.c402
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.h174
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.c334
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.h127
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.c201
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.h79
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.c195
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.h70
-rw-r--r--src/libcharon/kernel/kernel_interface.c386
-rw-r--r--src/libcharon/kernel/kernel_interface.h398
-rw-r--r--src/libcharon/kernel/kernel_ipsec.c29
-rw-r--r--src/libcharon/kernel/kernel_ipsec.h282
-rw-r--r--src/libcharon/kernel/kernel_net.h143
-rw-r--r--src/libcharon/network/packet.c138
-rw-r--r--src/libcharon/network/packet.h115
-rw-r--r--src/libcharon/network/receiver.c402
-rw-r--r--src/libcharon/network/receiver.h70
-rw-r--r--src/libcharon/network/sender.c165
-rw-r--r--src/libcharon/network/sender.h62
-rw-r--r--src/libcharon/network/socket.h64
-rw-r--r--src/libcharon/network/socket_manager.c129
-rw-r--r--src/libcharon/network/socket_manager.h74
-rw-r--r--src/libcharon/plugins/android/Makefile.am18
-rw-r--r--src/libcharon/plugins/android/Makefile.in590
-rw-r--r--src/libcharon/plugins/android/android_handler.c225
-rw-r--r--src/libcharon/plugins/android/android_handler.h50
-rw-r--r--src/libcharon/plugins/android/android_plugin.c66
-rw-r--r--src/libcharon/plugins/android/android_plugin.h42
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.am18
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in590
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_plugin.c81
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_plugin.h42
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c194
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.h54
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_socket.c758
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_socket.h60
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_transaction.c184
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_transaction.h109
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.am19
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in593
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_peer.c583
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_peer.h49
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_plugin.c51
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_plugin.h45
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_server.c700
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_server.h49
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.am20
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in596
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c178
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h53
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c394
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h125
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c87
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.h57
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c204
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h52
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.am16
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in587
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.c327
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.h60
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c56
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.am16
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in589
-rw-r--r--src/libcharon/plugins/eap_identity/eap_identity.c218
-rw-r--r--src/libcharon/plugins/eap_identity/eap_identity.h59
-rw-r--r--src/libcharon/plugins/eap_identity/eap_identity_plugin.c50
-rw-r--r--src/libcharon/plugins/eap_identity/eap_identity_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.am16
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in587
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5.c303
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5.h57
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5_plugin.c50
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.am17
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in590
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c1250
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h57
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c50
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.am19
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in594
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c312
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.h48
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.c54
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.h45
-rw-r--r--src/libcharon/plugins/eap_radius/radius_client.c495
-rw-r--r--src/libcharon/plugins/eap_radius/radius_client.h88
-rw-r--r--src/libcharon/plugins/eap_radius/radius_message.c476
-rw-r--r--src/libcharon/plugins/eap_radius/radius_message.h276
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.am19
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in593
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.c654
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.h57
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_plugin.c51
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_server.c611
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_server.h57
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.am19
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in595
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c107
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h53
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c90
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c93
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h50
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c260
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h56
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am18
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in594
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c154
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h49
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c81
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c182
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h49
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.am18
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in593
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c170
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h49
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c79
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c209
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h49
-rw-r--r--src/libcharon/plugins/farp/Makefile.am16
-rw-r--r--src/libcharon/plugins/farp/Makefile.in587
-rw-r--r--src/libcharon/plugins/farp/farp_listener.c154
-rw-r--r--src/libcharon/plugins/farp/farp_listener.h58
-rw-r--r--src/libcharon/plugins/farp/farp_plugin.c77
-rw-r--r--src/libcharon/plugins/farp/farp_plugin.h42
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.c198
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.h47
-rw-r--r--src/libcharon/plugins/ha/Makefile.am25
-rw-r--r--src/libcharon/plugins/ha/Makefile.in604
-rw-r--r--src/libcharon/plugins/ha/ha_child.c170
-rw-r--r--src/libcharon/plugins/ha/ha_child.h57
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c132
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.h47
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c737
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.h50
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c280
-rw-r--r--src/libcharon/plugins/ha/ha_ike.h57
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c229
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.h70
-rw-r--r--src/libcharon/plugins/ha/ha_message.c663
-rw-r--r--src/libcharon/plugins/ha/ha_message.h205
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c163
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.h47
-rw-r--r--src/libcharon/plugins/ha/ha_segments.c503
-rw-r--r--src/libcharon/plugins/ha/ha_segments.h111
-rw-r--r--src/libcharon/plugins/ha/ha_socket.c234
-rw-r--r--src/libcharon/plugins/ha/ha_socket.h60
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c298
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.h57
-rw-r--r--src/libcharon/plugins/kernel_klips/Makefile.am17
-rw-r--r--src/libcharon/plugins/kernel_klips/Makefile.in590
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c2657
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.h46
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_plugin.c56
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_plugin.h42
-rw-r--r--src/libcharon/plugins/kernel_klips/pfkeyv2.h322
-rw-r--r--src/libcharon/plugins/kernel_netlink/Makefile.am20
-rw-r--r--src/libcharon/plugins/kernel_netlink/Makefile.in597
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c2032
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h46
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c1506
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h46
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c59
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h42
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c306
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h77
-rw-r--r--src/libcharon/plugins/kernel_pfkey/Makefile.am17
-rw-r--r--src/libcharon/plugins/kernel_pfkey/Makefile.in590
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c2175
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h46
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c56
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h42
-rw-r--r--src/libcharon/plugins/kernel_pfroute/Makefile.am17
-rw-r--r--src/libcharon/plugins/kernel_pfroute/Makefile.in590
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c729
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h46
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c58
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h42
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.am21
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in600
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c333
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.h51
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_creds.c313
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_creds.h51
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c67
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_diffie_hellman.h48
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c176
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.h46
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_listener.c102
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_listener.h52
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c230
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.h44
-rw-r--r--src/libcharon/plugins/medcli/Makefile.am19
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in593
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c407
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.h53
-rw-r--r--src/libcharon/plugins/medcli/medcli_creds.c243
-rw-r--r--src/libcharon/plugins/medcli/medcli_creds.h53
-rw-r--r--src/libcharon/plugins/medcli/medcli_listener.c133
-rw-r--r--src/libcharon/plugins/medcli/medcli_listener.h53
-rw-r--r--src/libcharon/plugins/medcli/medcli_plugin.c109
-rw-r--r--src/libcharon/plugins/medcli/medcli_plugin.h42
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.am18
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in591
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c154
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.h53
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_creds.c163
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_creds.h53
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_plugin.c99
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_plugin.h42
-rw-r--r--src/libcharon/plugins/nm/Makefile.am21
-rw-r--r--src/libcharon/plugins/nm/Makefile.in595
-rw-r--r--src/libcharon/plugins/nm/nm_creds.c447
-rw-r--r--src/libcharon/plugins/nm/nm_creds.h85
-rw-r--r--src/libcharon/plugins/nm/nm_handler.c193
-rw-r--r--src/libcharon/plugins/nm/nm_handler.h62
-rw-r--r--src/libcharon/plugins/nm/nm_plugin.c130
-rw-r--r--src/libcharon/plugins/nm/nm_plugin.h42
-rw-r--r--src/libcharon/plugins/nm/nm_service.c629
-rw-r--r--src/libcharon/plugins/nm/nm_service.h55
-rw-r--r--src/libcharon/plugins/resolve/Makefile.am18
-rw-r--r--src/libcharon/plugins/resolve/Makefile.in591
-rw-r--r--src/libcharon/plugins/resolve/resolve_handler.c251
-rw-r--r--src/libcharon/plugins/resolve/resolve_handler.h49
-rw-r--r--src/libcharon/plugins/resolve/resolve_plugin.c62
-rw-r--r--src/libcharon/plugins/resolve/resolve_plugin.h42
-rw-r--r--src/libcharon/plugins/smp/Makefile.am17
-rw-r--r--src/libcharon/plugins/smp/Makefile.in586
-rw-r--r--src/libcharon/plugins/smp/smp.c768
-rw-r--r--src/libcharon/plugins/smp/smp.h45
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.am17
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in590
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_plugin.c69
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_plugin.h42
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c631
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.h49
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.am17
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in590
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c69
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.h42
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c620
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.h49
-rw-r--r--src/libcharon/plugins/socket_raw/Makefile.am17
-rw-r--r--src/libcharon/plugins/socket_raw/Makefile.in590
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_plugin.c69
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_plugin.h42
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.c709
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.h55
-rw-r--r--src/libcharon/plugins/sql/Makefile.am18
-rw-r--r--src/libcharon/plugins/sql/Makefile.in591
-rw-r--r--src/libcharon/plugins/sql/sql_config.c535
-rw-r--r--src/libcharon/plugins/sql/sql_config.h53
-rw-r--r--src/libcharon/plugins/sql/sql_cred.c365
-rw-r--r--src/libcharon/plugins/sql/sql_cred.h53
-rw-r--r--src/libcharon/plugins/sql/sql_logger.c145
-rw-r--r--src/libcharon/plugins/sql/sql_logger.h53
-rw-r--r--src/libcharon/plugins/sql/sql_plugin.c107
-rw-r--r--src/libcharon/plugins/sql/sql_plugin.h42
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am27
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in608
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c226
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.h86
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c458
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.h80
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c949
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h66
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c491
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.h88
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c1175
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.h84
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c1230
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.h74
-rw-r--r--src/libcharon/plugins/stroke/stroke_plugin.c65
-rw-r--r--src/libcharon/plugins/stroke/stroke_plugin.h45
-rw-r--r--src/libcharon/plugins/stroke/stroke_shared_key.c140
-rw-r--r--src/libcharon/plugins/stroke/stroke_shared_key.h60
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c671
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.h42
-rw-r--r--src/libcharon/plugins/uci/Makefile.am19
-rw-r--r--src/libcharon/plugins/uci/Makefile.in592
-rw-r--r--src/libcharon/plugins/uci/uci_config.c361
-rw-r--r--src/libcharon/plugins/uci/uci_config.h55
-rw-r--r--src/libcharon/plugins/uci/uci_control.c301
-rw-r--r--src/libcharon/plugins/uci/uci_control.h42
-rw-r--r--src/libcharon/plugins/uci/uci_creds.c174
-rw-r--r--src/libcharon/plugins/uci/uci_creds.h55
-rw-r--r--src/libcharon/plugins/uci/uci_parser.c186
-rw-r--r--src/libcharon/plugins/uci/uci_parser.h59
-rw-r--r--src/libcharon/plugins/uci/uci_plugin.c93
-rw-r--r--src/libcharon/plugins/uci/uci_plugin.h43
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.am29
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in708
-rw-r--r--src/libcharon/plugins/unit_tester/tests.h43
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_agent.c67
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_auth_info.c140
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_cert.c108
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_chunk.c82
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_curl.c44
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_enumerator.c306
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_id.c249
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_med_db.c54
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_mutex.c100
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_mysql.c89
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_pool.c93
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_rsa_gen.c120
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_sqlite.c93
-rw-r--r--src/libcharon/plugins/unit_tester/unit_tester.c116
-rw-r--r--src/libcharon/plugins/unit_tester/unit_tester.h44
-rw-r--r--src/libcharon/plugins/updown/Makefile.am17
-rw-r--r--src/libcharon/plugins/updown/Makefile.in589
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c294
-rw-r--r--src/libcharon/plugins/updown/updown_listener.h49
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.c63
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.h42
-rw-r--r--src/libcharon/processing/jobs/acquire_job.c86
-rw-r--r--src/libcharon/processing/jobs/acquire_job.h54
-rw-r--r--src/libcharon/processing/jobs/callback_job.c271
-rw-r--r--src/libcharon/processing/jobs/callback_job.h118
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.c100
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.h59
-rw-r--r--src/libcharon/processing/jobs/delete_ike_sa_job.c116
-rw-r--r--src/libcharon/processing/jobs/delete_ike_sa_job.h57
-rw-r--r--src/libcharon/processing/jobs/inactivity_job.c150
-rw-r--r--src/libcharon/processing/jobs/inactivity_job.h53
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.c271
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.h62
-rw-r--r--src/libcharon/processing/jobs/job.h52
-rw-r--r--src/libcharon/processing/jobs/mediation_job.c195
-rw-r--r--src/libcharon/processing/jobs/mediation_job.h74
-rw-r--r--src/libcharon/processing/jobs/migrate_job.c150
-rw-r--r--src/libcharon/processing/jobs/migrate_job.h61
-rw-r--r--src/libcharon/processing/jobs/process_message_job.c106
-rw-r--r--src/libcharon/processing/jobs/process_message_job.h49
-rw-r--r--src/libcharon/processing/jobs/rekey_child_sa_job.c97
-rw-r--r--src/libcharon/processing/jobs/rekey_child_sa_job.h57
-rw-r--r--src/libcharon/processing/jobs/rekey_ike_sa_job.c104
-rw-r--r--src/libcharon/processing/jobs/rekey_ike_sa_job.h51
-rw-r--r--src/libcharon/processing/jobs/retransmit_job.c93
-rw-r--r--src/libcharon/processing/jobs/retransmit_job.h55
-rw-r--r--src/libcharon/processing/jobs/roam_job.c106
-rw-r--r--src/libcharon/processing/jobs/roam_job.h52
-rw-r--r--src/libcharon/processing/jobs/send_dpd_job.c88
-rw-r--r--src/libcharon/processing/jobs/send_dpd_job.h52
-rw-r--r--src/libcharon/processing/jobs/send_keepalive_job.c82
-rw-r--r--src/libcharon/processing/jobs/send_keepalive_job.h51
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.c96
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.h50
-rw-r--r--src/libcharon/processing/processor.c273
-rw-r--r--src/libcharon/processing/processor.h94
-rw-r--r--src/libcharon/processing/scheduler.c358
-rw-r--r--src/libcharon/processing/scheduler.h130
-rw-r--r--src/libcharon/sa/authenticators/authenticator.c100
-rw-r--r--src/libcharon/sa/authenticators/authenticator.h178
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_manager.c170
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_manager.h82
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.c107
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.h205
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_manager.c534
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_manager.h514
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c705
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.h98
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.c201
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.h61
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.c265
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.h62
-rw-r--r--src/libcharon/sa/child_sa.c1015
-rw-r--r--src/libcharon/sa/child_sa.h337
-rw-r--r--src/libcharon/sa/connect_manager.c1623
-rw-r--r--src/libcharon/sa/connect_manager.h126
-rw-r--r--src/libcharon/sa/ike_sa.c2227
-rw-r--r--src/libcharon/sa/ike_sa.h921
-rw-r--r--src/libcharon/sa/ike_sa_id.c179
-rw-r--r--src/libcharon/sa/ike_sa_id.h126
-rw-r--r--src/libcharon/sa/ike_sa_manager.c1741
-rw-r--r--src/libcharon/sa/ike_sa_manager.h220
-rw-r--r--src/libcharon/sa/keymat.c617
-rw-r--r--src/libcharon/sa/keymat.h163
-rw-r--r--src/libcharon/sa/mediation_manager.c341
-rw-r--r--src/libcharon/sa/mediation_manager.h90
-rw-r--r--src/libcharon/sa/task_manager.c1083
-rw-r--r--src/libcharon/sa/task_manager.h173
-rw-r--r--src/libcharon/sa/tasks/child_create.c1351
-rw-r--r--src/libcharon/sa/tasks/child_create.h83
-rw-r--r--src/libcharon/sa/tasks/child_delete.c402
-rw-r--r--src/libcharon/sa/tasks/child_delete.h60
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c430
-rw-r--r--src/libcharon/sa/tasks/child_rekey.h64
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c1041
-rw-r--r--src/libcharon/sa/tasks/ike_auth.h57
-rw-r--r--src/libcharon/sa/tasks/ike_auth_lifetime.c182
-rw-r--r--src/libcharon/sa/tasks/ike_auth_lifetime.h53
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.c261
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.h53
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c524
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.h53
-rw-r--r--src/libcharon/sa/tasks/ike_config.c448
-rw-r--r--src/libcharon/sa/tasks/ike_config.h51
-rw-r--r--src/libcharon/sa/tasks/ike_delete.c210
-rw-r--r--src/libcharon/sa/tasks/ike_delete.h50
-rw-r--r--src/libcharon/sa/tasks/ike_dpd.c99
-rw-r--r--src/libcharon/sa/tasks/ike_dpd.h51
-rw-r--r--src/libcharon/sa/tasks/ike_init.c600
-rw-r--r--src/libcharon/sa/tasks/ike_init.h60
-rw-r--r--src/libcharon/sa/tasks/ike_me.c856
-rw-r--r--src/libcharon/sa/tasks/ike_me.h100
-rw-r--r--src/libcharon/sa/tasks/ike_mobike.c659
-rw-r--r--src/libcharon/sa/tasks/ike_mobike.h88
-rw-r--r--src/libcharon/sa/tasks/ike_natd.c490
-rw-r--r--src/libcharon/sa/tasks/ike_natd.h59
-rw-r--r--src/libcharon/sa/tasks/ike_reauth.c196
-rw-r--r--src/libcharon/sa/tasks/ike_reauth.h51
-rw-r--r--src/libcharon/sa/tasks/ike_rekey.c409
-rw-r--r--src/libcharon/sa/tasks/ike_rekey.h61
-rw-r--r--src/libcharon/sa/tasks/ike_vendor.c139
-rw-r--r--src/libcharon/sa/tasks/ike_vendor.h49
-rw-r--r--src/libcharon/sa/tasks/task.c58
-rw-r--r--src/libcharon/sa/tasks/task.h150
-rw-r--r--src/libcharon/sa/trap_manager.c403
-rw-r--r--src/libcharon/sa/trap_manager.h81
-rw-r--r--src/libfast/Makefile.am2
-rw-r--r--src/libfast/Makefile.in6
-rw-r--r--src/libfast/request.c41
-rw-r--r--src/libfast/request.h9
-rw-r--r--src/libfast/session.c4
-rw-r--r--src/libfast/smtp.c185
-rw-r--r--src/libfast/smtp.h56
-rw-r--r--src/libfreeswan/Makefile.in1
-rw-r--r--src/libfreeswan/pfkeyv2.h1
-rw-r--r--src/libhydra/Android.mk34
-rw-r--r--src/libhydra/Makefile.am42
-rw-r--r--src/libhydra/Makefile.in762
-rw-r--r--src/libhydra/attributes/attribute_handler.h72
-rw-r--r--src/libhydra/attributes/attribute_manager.c374
-rw-r--r--src/libhydra/attributes/attribute_manager.h149
-rw-r--r--src/libhydra/attributes/attribute_provider.h67
-rw-r--r--src/libhydra/attributes/attributes.c43
-rw-r--r--src/libhydra/attributes/attributes.h62
-rw-r--r--src/libhydra/attributes/mem_pool.c451
-rw-r--r--src/libhydra/attributes/mem_pool.h110
-rw-r--r--src/libhydra/hydra.c73
-rw-r--r--src/libhydra/hydra.h76
-rw-r--r--src/libhydra/plugins/attr/Makefile.am17
-rw-r--r--src/libhydra/plugins/attr/Makefile.in586
-rw-r--r--src/libhydra/plugins/attr/attr_plugin.c63
-rw-r--r--src/libhydra/plugins/attr/attr_plugin.h42
-rw-r--r--src/libhydra/plugins/attr/attr_provider.c240
-rw-r--r--src/libhydra/plugins/attr/attr_provider.h49
-rw-r--r--src/libhydra/plugins/attr_sql/Makefile.am23
-rw-r--r--src/libhydra/plugins/attr_sql/Makefile.in649
-rw-r--r--src/libhydra/plugins/attr_sql/attr_sql_plugin.c88
-rw-r--r--src/libhydra/plugins/attr_sql/attr_sql_plugin.h42
-rw-r--r--src/libhydra/plugins/attr_sql/pool.c1402
-rw-r--r--src/libhydra/plugins/attr_sql/sql_attribute.c384
-rw-r--r--src/libhydra/plugins/attr_sql/sql_attribute.h50
-rw-r--r--src/libsimaka/Makefile.am2
-rw-r--r--src/libsimaka/Makefile.in3
-rw-r--r--src/libsimaka/simaka_message.c22
-rw-r--r--src/libsimaka/simaka_message.h1
-rw-r--r--src/libstrongswan/Android.mk121
-rw-r--r--src/libstrongswan/AndroidConfigLocal.h9
-rw-r--r--src/libstrongswan/Makefile.am99
-rw-r--r--src/libstrongswan/Makefile.in187
-rw-r--r--src/libstrongswan/asn1/asn1.c36
-rw-r--r--src/libstrongswan/asn1/asn1.h3
-rw-r--r--src/libstrongswan/asn1/asn1_parser.c19
-rw-r--r--src/libstrongswan/asn1/asn1_parser.h6
-rw-r--r--src/libstrongswan/asn1/oid.h1
-rw-r--r--src/libstrongswan/asn1/oid.txt2
-rw-r--r--src/libstrongswan/chunk.c14
-rw-r--r--src/libstrongswan/chunk.h2
-rw-r--r--src/libstrongswan/credentials/credential_factory.c2
-rw-r--r--src/libstrongswan/credentials/keys/key_encoding.h2
-rw-r--r--src/libstrongswan/credentials/keys/shared_key.h2
-rw-r--r--src/libstrongswan/crypto/crypto_factory.c2
-rw-r--r--src/libstrongswan/crypto/crypto_tester.c40
-rw-r--r--src/libstrongswan/crypto/diffie_hellman.c407
-rw-r--r--src/libstrongswan/crypto/diffie_hellman.h45
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.c263
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.txt184
-rw-r--r--src/libstrongswan/debug.c34
-rw-r--r--src/libstrongswan/debug.h83
-rw-r--r--src/libstrongswan/enum.h2
-rw-r--r--src/libstrongswan/fetcher/fetcher_manager.c2
-rw-r--r--src/libstrongswan/integrity_checker.c41
-rw-r--r--src/libstrongswan/integrity_checker.h4
-rw-r--r--src/libstrongswan/library.c18
-rw-r--r--src/libstrongswan/library.h28
-rw-r--r--src/libstrongswan/plugins/aes/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/aes/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/aes/aes_plugin.c2
-rw-r--r--src/libstrongswan/plugins/aes/aes_plugin.h5
-rw-r--r--src/libstrongswan/plugins/agent/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/agent/Makefile.in54
-rw-r--r--src/libstrongswan/plugins/agent/agent_plugin.c2
-rw-r--r--src/libstrongswan/plugins/agent/agent_plugin.h5
-rw-r--r--src/libstrongswan/plugins/agent/agent_private_key.c26
-rw-r--r--src/libstrongswan/plugins/blowfish/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/blowfish/Makefile.in53
-rw-r--r--src/libstrongswan/plugins/blowfish/blowfish_plugin.c2
-rw-r--r--src/libstrongswan/plugins/blowfish/blowfish_plugin.h5
-rw-r--r--src/libstrongswan/plugins/curl/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/curl/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/curl/curl_fetcher.c4
-rw-r--r--src/libstrongswan/plugins/curl/curl_plugin.c4
-rw-r--r--src/libstrongswan/plugins/curl/curl_plugin.h5
-rw-r--r--src/libstrongswan/plugins/des/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/des/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/des/des_plugin.c2
-rw-r--r--src/libstrongswan/plugins/des/des_plugin.h5
-rw-r--r--src/libstrongswan/plugins/dnskey/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/dnskey/Makefile.in54
-rw-r--r--src/libstrongswan/plugins/dnskey/dnskey_builder.c9
-rw-r--r--src/libstrongswan/plugins/dnskey/dnskey_plugin.c2
-rw-r--r--src/libstrongswan/plugins/dnskey/dnskey_plugin.h5
-rw-r--r--src/libstrongswan/plugins/fips_prf/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/fips_prf/Makefile.in53
-rw-r--r--src/libstrongswan/plugins/fips_prf/fips_prf.c6
-rw-r--r--src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c2
-rw-r--r--src/libstrongswan/plugins/fips_prf/fips_prf_plugin.h5
-rw-r--r--src/libstrongswan/plugins/gcrypt/Makefile.am7
-rw-r--r--src/libstrongswan/plugins/gcrypt/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c2
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_dh.c351
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c2
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c10
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_plugin.h5
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c32
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c28
-rw-r--r--src/libstrongswan/plugins/gmp/Makefile.am16
-rw-r--r--src/libstrongswan/plugins/gmp/Makefile.in57
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c392
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_plugin.c8
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_plugin.h5
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c29
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c40
-rw-r--r--src/libstrongswan/plugins/hmac/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/hmac/Makefile.in51
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_plugin.c2
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_plugin.h5
-rw-r--r--src/libstrongswan/plugins/ldap/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/ldap/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/ldap/ldap_fetcher.c17
-rw-r--r--src/libstrongswan/plugins/ldap/ldap_plugin.c2
-rw-r--r--src/libstrongswan/plugins/ldap/ldap_plugin.h5
-rw-r--r--src/libstrongswan/plugins/md4/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/md4/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/md4/md4_plugin.c2
-rw-r--r--src/libstrongswan/plugins/md4/md4_plugin.h5
-rw-r--r--src/libstrongswan/plugins/md5/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/md5/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/md5/md5_plugin.c2
-rw-r--r--src/libstrongswan/plugins/md5/md5_plugin.h5
-rw-r--r--src/libstrongswan/plugins/mysql/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/mysql/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/mysql/mysql_database.c28
-rw-r--r--src/libstrongswan/plugins/mysql/mysql_plugin.c4
-rw-r--r--src/libstrongswan/plugins/mysql/mysql_plugin.h5
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.am8
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.in61
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c78
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c4
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_private_key.c27
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_public_key.c25
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c15
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.h5
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c58
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c21
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_sha1_prf.c139
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_sha1_prf.h48
-rw-r--r--src/libstrongswan/plugins/padlock/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/padlock/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_plugin.c6
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_plugin.h5
-rw-r--r--src/libstrongswan/plugins/pem/Makefile.am11
-rw-r--r--src/libstrongswan/plugins/pem/Makefile.in58
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c35
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.h6
-rw-r--r--src/libstrongswan/plugins/pem/pem_encoder.c138
-rw-r--r--src/libstrongswan/plugins/pem/pem_encoder.h33
-rw-r--r--src/libstrongswan/plugins/pem/pem_plugin.c7
-rw-r--r--src/libstrongswan/plugins/pem/pem_plugin.h5
-rw-r--r--src/libstrongswan/plugins/pgp/Makefile.am16
-rw-r--r--src/libstrongswan/plugins/pgp/Makefile.in59
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_builder.c13
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_cert.c32
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_encoder.c3
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_plugin.c2
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_plugin.h5
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_utils.c18
-rw-r--r--src/libstrongswan/plugins/pkcs1/Makefile.am12
-rw-r--r--src/libstrongswan/plugins/pkcs1/Makefile.in56
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_builder.c6
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_builder.h2
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c3
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c2
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_plugin.h5
-rw-r--r--src/libstrongswan/plugins/plugin.h4
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c74
-rw-r--r--src/libstrongswan/plugins/pubkey/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/pubkey/Makefile.in54
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_plugin.c2
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_plugin.h5
-rw-r--r--src/libstrongswan/plugins/random/Makefile.am11
-rw-r--r--src/libstrongswan/plugins/random/Makefile.in54
-rw-r--r--src/libstrongswan/plugins/random/random_plugin.c2
-rw-r--r--src/libstrongswan/plugins/random/random_plugin.h5
-rw-r--r--src/libstrongswan/plugins/random/random_rng.c4
-rw-r--r--src/libstrongswan/plugins/sha1/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/sha1/Makefile.in51
-rw-r--r--src/libstrongswan/plugins/sha1/sha1_plugin.c2
-rw-r--r--src/libstrongswan/plugins/sha1/sha1_plugin.h5
-rw-r--r--src/libstrongswan/plugins/sha2/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/sha2/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/sha2/sha2_plugin.c2
-rw-r--r--src/libstrongswan/plugins/sha2/sha2_plugin.h5
-rw-r--r--src/libstrongswan/plugins/sqlite/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/sqlite/Makefile.in52
-rw-r--r--src/libstrongswan/plugins/sqlite/sqlite_database.c15
-rw-r--r--src/libstrongswan/plugins/sqlite/sqlite_plugin.c2
-rw-r--r--src/libstrongswan/plugins/sqlite/sqlite_plugin.h5
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.am6
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.in49
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors/rng.c6
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c2
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors_plugin.h5
-rw-r--r--src/libstrongswan/plugins/x509/Makefile.am21
-rw-r--r--src/libstrongswan/plugins/x509/Makefile.in63
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c35
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c78
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c15
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_request.c15
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_response.c20
-rw-r--r--src/libstrongswan/plugins/x509/x509_pkcs10.c27
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.c2
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.h5
-rw-r--r--src/libstrongswan/plugins/xcbc/Makefile.am9
-rw-r--r--src/libstrongswan/plugins/xcbc/Makefile.in51
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_plugin.c2
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_plugin.h5
-rw-r--r--src/libstrongswan/printf_hook.c12
-rw-r--r--src/libstrongswan/selectors/traffic_selector.h28
-rw-r--r--src/libstrongswan/settings.c14
-rw-r--r--src/libstrongswan/settings.h4
-rw-r--r--src/libstrongswan/threading/mutex.c4
-rw-r--r--src/libstrongswan/threading/rwlock.c6
-rw-r--r--src/libstrongswan/threading/thread.c14
-rw-r--r--src/libstrongswan/threading/thread.h6
-rw-r--r--src/libstrongswan/utils.c34
-rw-r--r--src/libstrongswan/utils.h18
-rw-r--r--src/libstrongswan/utils/enumerator.c15
-rw-r--r--src/libstrongswan/utils/enumerator.h2
-rw-r--r--src/libstrongswan/utils/host.c2
-rw-r--r--src/libstrongswan/utils/identification.c4
-rw-r--r--src/libstrongswan/utils/leak_detective.c1
-rw-r--r--src/libstrongswan/utils/optionsfrom.c7
-rw-r--r--src/manager/Makefile.am3
-rw-r--r--src/manager/Makefile.in9
-rw-r--r--src/manager/main.c3
-rw-r--r--src/medsrv/Makefile.am3
-rw-r--r--src/medsrv/Makefile.in8
-rw-r--r--src/openac/Makefile.am2
-rw-r--r--src/openac/Makefile.in2
-rwxr-xr-xsrc/openac/openac.c13
-rw-r--r--src/pki/Makefile.am4
-rw-r--r--src/pki/Makefile.in4
-rw-r--r--src/pki/commands/gen.c2
-rw-r--r--src/pki/commands/issue.c13
-rw-r--r--src/pki/commands/self.c5
-rw-r--r--src/pluto/Makefile.am6
-rw-r--r--src/pluto/Makefile.in20
-rw-r--r--src/pluto/ac.c27
-rw-r--r--src/pluto/alg_info.c3
-rw-r--r--src/pluto/ca.c4
-rw-r--r--src/pluto/connections.c55
-rw-r--r--src/pluto/connections.h1
-rw-r--r--src/pluto/constants.c10
-rw-r--r--src/pluto/constants.h7
-rw-r--r--src/pluto/crypto.c34
-rw-r--r--src/pluto/demux.h1
-rw-r--r--src/pluto/fetch.c11
-rw-r--r--src/pluto/ipsec_doi.c44
-rw-r--r--src/pluto/kernel.c1
-rw-r--r--src/pluto/kernel_alg.c4
-rw-r--r--src/pluto/kernel_netlink.c2
-rw-r--r--src/pluto/lex.c2
-rw-r--r--src/pluto/log.c6
-rw-r--r--src/pluto/modecfg.c69
-rw-r--r--src/pluto/pkcs7.c88
-rw-r--r--src/pluto/plutomain.c15
-rw-r--r--src/pluto/rcv_whack.c46
-rw-r--r--src/pluto/timer.c2
-rw-r--r--src/pluto/vendor.c131
-rw-r--r--src/pluto/vendor.h64
-rw-r--r--src/pluto/whack_attribute.c365
-rw-r--r--src/pluto/whack_attribute.h111
-rw-r--r--src/pluto/x509.c4
-rw-r--r--src/scepclient/Makefile.am4
-rw-r--r--src/scepclient/Makefile.in5
-rw-r--r--src/scepclient/loglite.c2
-rw-r--r--src/scepclient/scepclient.c2
-rw-r--r--src/starter/Makefile.am2
-rw-r--r--src/starter/Makefile.in3
-rw-r--r--src/starter/args.c3
-rw-r--r--src/starter/cmp.c1
-rw-r--r--src/starter/confread.c64
-rw-r--r--src/starter/confread.h1
-rw-r--r--src/starter/ipsec.conf.57
-rw-r--r--src/starter/keywords.c224
-rw-r--r--src/starter/keywords.h3
-rw-r--r--src/starter/keywords.txt2
-rw-r--r--src/starter/lex.yy.c44
-rw-r--r--src/starter/parser.l4
-rw-r--r--src/starter/parser.y16
-rw-r--r--src/starter/starter.c11
-rw-r--r--src/starter/starterstroke.c1
-rw-r--r--src/starter/starterwhack.c29
-rw-r--r--src/starter/y.tab.c325
-rw-r--r--src/starter/y.tab.h42
-rw-r--r--src/stroke/Makefile.in1
-rw-r--r--src/stroke/stroke.c9
-rw-r--r--src/stroke/stroke_msg.h1
-rw-r--r--src/whack/Makefile.in1
-rw-r--r--src/whack/whack.c41
-rw-r--r--src/whack/whack.h6
836 files changed, 138978 insertions, 5457 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ae3ec8a20..8d4dd2e37 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,6 +4,10 @@ if USE_LIBSTRONGSWAN
SUBDIRS += libstrongswan
endif
+if USE_LIBHYDRA
+ SUBDIRS += libhydra
+endif
+
if USE_SIMAKA
SUBDIRS += libsimaka
endif
@@ -17,7 +21,7 @@ if USE_PLUTO
endif
if USE_CHARON
- SUBDIRS += charon
+ SUBDIRS += libcharon charon
endif
if USE_STROKE
@@ -29,7 +33,7 @@ if USE_UPDOWN
endif
if USE_TOOLS
- SUBDIRS += openac scepclient pki
+ SUBDIRS += libfreeswan openac scepclient pki
endif
if USE_DUMM
diff --git a/src/Makefile.in b/src/Makefile.in
index 2e305f50a..2a04c8b19 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -34,18 +34,19 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@USE_LIBSTRONGSWAN_TRUE@am__append_1 = libstrongswan
-@USE_SIMAKA_TRUE@am__append_2 = libsimaka
-@USE_FILE_CONFIG_TRUE@am__append_3 = libfreeswan starter ipsec _copyright
-@USE_PLUTO_TRUE@am__append_4 = pluto whack
-@USE_CHARON_TRUE@am__append_5 = charon
-@USE_STROKE_TRUE@am__append_6 = stroke
-@USE_UPDOWN_TRUE@am__append_7 = _updown _updown_espmark
-@USE_TOOLS_TRUE@am__append_8 = openac scepclient pki
-@USE_DUMM_TRUE@am__append_9 = dumm
-@USE_FAST_TRUE@am__append_10 = libfast
-@USE_MANAGER_TRUE@am__append_11 = manager
-@USE_MEDSRV_TRUE@am__append_12 = medsrv
-@USE_INTEGRITY_TEST_TRUE@am__append_13 = checksum
+@USE_LIBHYDRA_TRUE@am__append_2 = libhydra
+@USE_SIMAKA_TRUE@am__append_3 = libsimaka
+@USE_FILE_CONFIG_TRUE@am__append_4 = libfreeswan starter ipsec _copyright
+@USE_PLUTO_TRUE@am__append_5 = pluto whack
+@USE_CHARON_TRUE@am__append_6 = libcharon charon
+@USE_STROKE_TRUE@am__append_7 = stroke
+@USE_UPDOWN_TRUE@am__append_8 = _updown _updown_espmark
+@USE_TOOLS_TRUE@am__append_9 = libfreeswan openac scepclient pki
+@USE_DUMM_TRUE@am__append_10 = dumm
+@USE_FAST_TRUE@am__append_11 = libfast
+@USE_MANAGER_TRUE@am__append_12 = manager
+@USE_MEDSRV_TRUE@am__append_13 = medsrv
+@USE_INTEGRITY_TEST_TRUE@am__append_14 = checksum
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -78,10 +79,10 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
distdir
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = . include libstrongswan libsimaka libfreeswan starter \
- ipsec _copyright pluto whack charon stroke _updown \
- _updown_espmark openac scepclient pki dumm libfast manager \
- medsrv checksum
+DIST_SUBDIRS = . include libstrongswan libhydra libsimaka libfreeswan \
+ starter ipsec _copyright pluto whack libcharon charon stroke \
+ _updown _updown_espmark openac scepclient pki dumm libfast \
+ manager medsrv checksum
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -228,6 +229,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -266,7 +268,7 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_6) \
$(am__append_7) $(am__append_8) $(am__append_9) \
$(am__append_10) $(am__append_11) $(am__append_12) \
- $(am__append_13)
+ $(am__append_13) $(am__append_14)
EXTRA_DIST = strongswan.conf
all: all-recursive
diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in
index fe529a151..d4e1c157b 100644
--- a/src/_copyright/Makefile.in
+++ b/src/_copyright/Makefile.in
@@ -221,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in
index e99238ed8..cf153461d 100644
--- a/src/_updown/Makefile.in
+++ b/src/_updown/Makefile.in
@@ -200,6 +200,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/_updown_espmark/Makefile.in b/src/_updown_espmark/Makefile.in
index ed88b67a6..a4379b44c 100644
--- a/src/_updown_espmark/Makefile.in
+++ b/src/_updown_espmark/Makefile.in
@@ -200,6 +200,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/charon/Android.mk b/src/charon/Android.mk
new file mode 100644
index 000000000..491d7f946
--- /dev/null
+++ b/src/charon/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+charon.c
+
+# build charon -----------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/libhydra \
+ $(strongswan_PATH)/src/libcharon \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := charon
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libcharon
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index e20d45cf8..6481947f1 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -1,275 +1,22 @@
ipsec_PROGRAMS = charon
charon_SOURCES = \
-bus/bus.c bus/bus.h \
-bus/listeners/listener.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 config/peer_cfg.h \
-config/proposal.c config/proposal.h \
-config/auth_cfg.c config/auth_cfg.h \
-control/controller.c control/controller.h \
-daemon.c daemon.h \
-encoding/generator.c encoding/generator.h \
-encoding/message.c encoding/message.h \
-encoding/parser.c encoding/parser.h \
-encoding/payloads/auth_payload.c encoding/payloads/auth_payload.h \
-encoding/payloads/cert_payload.c encoding/payloads/cert_payload.h \
-encoding/payloads/certreq_payload.c encoding/payloads/certreq_payload.h \
-encoding/payloads/configuration_attribute.c encoding/payloads/configuration_attribute.h \
-encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
-encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
-encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
-encoding/payloads/encodings.c encoding/payloads/encodings.h \
-encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
-encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
-encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
-encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
-encoding/payloads/nonce_payload.c encoding/payloads/nonce_payload.h \
-encoding/payloads/notify_payload.c encoding/payloads/notify_payload.h \
-encoding/payloads/payload.c encoding/payloads/payload.h \
-encoding/payloads/proposal_substructure.c encoding/payloads/proposal_substructure.h \
-encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
-encoding/payloads/traffic_selector_substructure.c encoding/payloads/traffic_selector_substructure.h \
-encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
-encoding/payloads/transform_substructure.c encoding/payloads/transform_substructure.h \
-encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
-encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
-encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
-kernel/kernel_interface.c kernel/kernel_interface.h \
-kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
-kernel/kernel_net.h \
-network/packet.c network/packet.h \
-network/receiver.c network/receiver.h \
-network/sender.c network/sender.h \
-network/socket.h \
-processing/jobs/job.h \
-processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
-processing/jobs/callback_job.c processing/jobs/callback_job.h \
-processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
-processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
-processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
-processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
-processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
-processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
-processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
-processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
-processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
-processing/jobs/roam_job.c processing/jobs/roam_job.h \
-processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
-processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
-processing/scheduler.c processing/scheduler.h \
-processing/processor.c processing/processor.h \
-sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
-sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
-sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
-sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
-sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \
-sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
-sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
-sa/child_sa.c sa/child_sa.h \
-sa/ike_sa.c sa/ike_sa.h \
-sa/ike_sa_id.c sa/ike_sa_id.h \
-sa/ike_sa_manager.c sa/ike_sa_manager.h \
-sa/task_manager.c sa/task_manager.h \
-sa/keymat.c sa/keymat.h \
-sa/trap_manager.c sa/trap_manager.h \
-sa/tasks/child_create.c sa/tasks/child_create.h \
-sa/tasks/child_delete.c sa/tasks/child_delete.h \
-sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
-sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
-sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
-sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
-sa/tasks/ike_config.c sa/tasks/ike_config.h \
-sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
-sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
-sa/tasks/ike_init.c sa/tasks/ike_init.h \
-sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
-sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
-sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
-sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
-sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
-sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
-sa/tasks/task.c sa/tasks/task.h \
-credentials/credential_manager.c credentials/credential_manager.h \
-credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
-credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
-credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
-credentials/credential_set.h
+charon.c
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
-AM_CFLAGS = -rdynamic \
- -DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\"
-charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB)
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
-# compile options
-#################
+AM_CFLAGS = \
+ -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_PIDDIR=\"${piddir}\"
-# Use RAW socket if pluto gets built
-if USE_PLUTO
- charon_SOURCES += network/socket-raw.c
-else
- charon_SOURCES += network/socket.c
-endif
+charon_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ -lm $(PTHREADLIB) $(DLLIB)
-if USE_ME
- charon_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
- processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
- processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
- sa/connect_manager.c sa/connect_manager.h \
- sa/mediation_manager.c sa/mediation_manager.h \
- sa/tasks/ike_me.c sa/tasks/ike_me.h
-endif
-
-if USE_CAPABILITIES
- charon_LDADD += -lcap
-endif
-
-
-# build optional plugins
-########################
-
-SUBDIRS = .
-PLUGINS = ${libstrongswan_plugins}
-
-if USE_LOAD_TESTER
- SUBDIRS += plugins/load_tester
- PLUGINS += load-tester
-endif
-
-if USE_KERNEL_PFKEY
- SUBDIRS += plugins/kernel_pfkey
- PLUGINS += kernel-pfkey
-endif
-
-if USE_KERNEL_PFROUTE
- SUBDIRS += plugins/kernel_pfroute
- PLUGINS += kernel-pfroute
-endif
-
-if USE_KERNEL_KLIPS
- SUBDIRS += plugins/kernel_klips
- PLUGINS += kernel-klips
-endif
-
-if USE_KERNEL_NETLINK
- SUBDIRS += plugins/kernel_netlink
- PLUGINS += kernel-netlink
-endif
-
-if USE_STROKE
- SUBDIRS += plugins/stroke
- PLUGINS += stroke
-endif
-
-if USE_SMP
- SUBDIRS += plugins/smp
- PLUGINS += smp
-endif
-
-if USE_SQL
- SUBDIRS += plugins/sql
- PLUGINS += sql
-endif
-
-if USE_UPDOWN
- SUBDIRS += plugins/updown
- PLUGINS += updown
-endif
-
-if USE_ATTR
- SUBDIRS += plugins/attr
- PLUGINS += attr
-endif
-
-if USE_EAP_IDENTITY
- SUBDIRS += plugins/eap_identity
- PLUGINS += eap-identity
-endif
-
-if USE_EAP_SIM
- SUBDIRS += plugins/eap_sim
- PLUGINS += eap-sim
-endif
-
-if USE_EAP_SIM_FILE
- SUBDIRS += plugins/eap_sim_file
- PLUGINS += eap-sim-file
-endif
-
-if USE_EAP_SIMAKA_PSEUDONYM
- SUBDIRS += plugins/eap_simaka_pseudonym
- PLUGINS += eap-simaka-pseudonym
-endif
-
-if USE_EAP_SIMAKA_REAUTH
- SUBDIRS += plugins/eap_simaka_reauth
- PLUGINS += eap-simaka-reauth
-endif
-
-if USE_EAP_MD5
- SUBDIRS += plugins/eap_md5
- PLUGINS += eap-md5
-endif
-
-if USE_EAP_GTC
- SUBDIRS += plugins/eap_gtc
- PLUGINS += eap-gtc
-endif
-
-if USE_EAP_AKA
- SUBDIRS += plugins/eap_aka
- PLUGINS += eap-aka
-endif
-
-if USE_EAP_AKA_3GPP2
- SUBDIRS += plugins/eap_aka_3gpp2
- PLUGINS += eap-aka-3gpp2
-endif
-
-if USE_EAP_MSCHAPV2
- SUBDIRS += plugins/eap_mschapv2
- PLUGINS += eap-mschapv2
-endif
-
-if USE_EAP_RADIUS
- SUBDIRS += plugins/eap_radius
- PLUGINS += eap-radius
-endif
-
-if USE_MEDSRV
- SUBDIRS += plugins/medsrv
- PLUGINS += medsrv
-endif
-
-if USE_MEDCLI
- SUBDIRS += plugins/medcli
- PLUGINS += medcli
-endif
-
-if USE_NM
- SUBDIRS += plugins/nm
- PLUGINS += nm
-endif
-
-if USE_RESOLVE
- SUBDIRS += plugins/resolve
- PLUGINS += resolve
-endif
-
-if USE_UCI
- SUBDIRS += plugins/uci
- PLUGINS += uci
-endif
-
-if USE_UNIT_TESTS
- SUBDIRS += plugins/unit_tester
- PLUGINS += unit-tester
-endif
-
-AM_CFLAGS += -DPLUGINS=\""${PLUGINS}\""
+EXTRA_DIST = Android.mk
diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in
index d7339b226..66690a37a 100644
--- a/src/charon/Makefile.in
+++ b/src/charon/Makefile.in
@@ -35,75 +35,6 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
ipsec_PROGRAMS = charon$(EXEEXT)
-
-# compile options
-#################
-
-# Use RAW socket if pluto gets built
-@USE_PLUTO_TRUE@am__append_1 = network/socket-raw.c
-@USE_PLUTO_FALSE@am__append_2 = network/socket.c
-@USE_ME_TRUE@am__append_3 = 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/connect_manager.c sa/connect_manager.h \
-@USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \
-@USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h
-
-@USE_CAPABILITIES_TRUE@am__append_4 = -lcap
-@USE_LOAD_TESTER_TRUE@am__append_5 = plugins/load_tester
-@USE_LOAD_TESTER_TRUE@am__append_6 = load-tester
-@USE_KERNEL_PFKEY_TRUE@am__append_7 = plugins/kernel_pfkey
-@USE_KERNEL_PFKEY_TRUE@am__append_8 = kernel-pfkey
-@USE_KERNEL_PFROUTE_TRUE@am__append_9 = plugins/kernel_pfroute
-@USE_KERNEL_PFROUTE_TRUE@am__append_10 = kernel-pfroute
-@USE_KERNEL_KLIPS_TRUE@am__append_11 = plugins/kernel_klips
-@USE_KERNEL_KLIPS_TRUE@am__append_12 = kernel-klips
-@USE_KERNEL_NETLINK_TRUE@am__append_13 = plugins/kernel_netlink
-@USE_KERNEL_NETLINK_TRUE@am__append_14 = kernel-netlink
-@USE_STROKE_TRUE@am__append_15 = plugins/stroke
-@USE_STROKE_TRUE@am__append_16 = stroke
-@USE_SMP_TRUE@am__append_17 = plugins/smp
-@USE_SMP_TRUE@am__append_18 = smp
-@USE_SQL_TRUE@am__append_19 = plugins/sql
-@USE_SQL_TRUE@am__append_20 = sql
-@USE_UPDOWN_TRUE@am__append_21 = plugins/updown
-@USE_UPDOWN_TRUE@am__append_22 = updown
-@USE_ATTR_TRUE@am__append_23 = plugins/attr
-@USE_ATTR_TRUE@am__append_24 = attr
-@USE_EAP_IDENTITY_TRUE@am__append_25 = plugins/eap_identity
-@USE_EAP_IDENTITY_TRUE@am__append_26 = eap-identity
-@USE_EAP_SIM_TRUE@am__append_27 = plugins/eap_sim
-@USE_EAP_SIM_TRUE@am__append_28 = eap-sim
-@USE_EAP_SIM_FILE_TRUE@am__append_29 = plugins/eap_sim_file
-@USE_EAP_SIM_FILE_TRUE@am__append_30 = eap-sim-file
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_31 = plugins/eap_simaka_pseudonym
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_32 = eap-simaka-pseudonym
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_33 = plugins/eap_simaka_reauth
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_34 = eap-simaka-reauth
-@USE_EAP_MD5_TRUE@am__append_35 = plugins/eap_md5
-@USE_EAP_MD5_TRUE@am__append_36 = eap-md5
-@USE_EAP_GTC_TRUE@am__append_37 = plugins/eap_gtc
-@USE_EAP_GTC_TRUE@am__append_38 = eap-gtc
-@USE_EAP_AKA_TRUE@am__append_39 = plugins/eap_aka
-@USE_EAP_AKA_TRUE@am__append_40 = eap-aka
-@USE_EAP_AKA_3GPP2_TRUE@am__append_41 = plugins/eap_aka_3gpp2
-@USE_EAP_AKA_3GPP2_TRUE@am__append_42 = eap-aka-3gpp2
-@USE_EAP_MSCHAPV2_TRUE@am__append_43 = plugins/eap_mschapv2
-@USE_EAP_MSCHAPV2_TRUE@am__append_44 = eap-mschapv2
-@USE_EAP_RADIUS_TRUE@am__append_45 = plugins/eap_radius
-@USE_EAP_RADIUS_TRUE@am__append_46 = eap-radius
-@USE_MEDSRV_TRUE@am__append_47 = plugins/medsrv
-@USE_MEDSRV_TRUE@am__append_48 = medsrv
-@USE_MEDCLI_TRUE@am__append_49 = plugins/medcli
-@USE_MEDCLI_TRUE@am__append_50 = medcli
-@USE_NM_TRUE@am__append_51 = plugins/nm
-@USE_NM_TRUE@am__append_52 = nm
-@USE_RESOLVE_TRUE@am__append_53 = plugins/resolve
-@USE_RESOLVE_TRUE@am__append_54 = resolve
-@USE_UCI_TRUE@am__append_55 = plugins/uci
-@USE_UCI_TRUE@am__append_56 = uci
-@USE_UNIT_TESTS_TRUE@am__append_57 = plugins/unit_tester
-@USE_UNIT_TESTS_TRUE@am__append_58 = unit-tester
subdir = src/charon
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -122,186 +53,13 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(ipsecdir)"
PROGRAMS = $(ipsec_PROGRAMS)
-am__charon_SOURCES_DIST = bus/bus.c bus/bus.h bus/listeners/listener.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 \
- config/peer_cfg.h config/proposal.c config/proposal.h \
- config/auth_cfg.c config/auth_cfg.h control/controller.c \
- control/controller.h daemon.c daemon.h encoding/generator.c \
- encoding/generator.h encoding/message.c encoding/message.h \
- encoding/parser.c encoding/parser.h \
- encoding/payloads/auth_payload.c \
- encoding/payloads/auth_payload.h \
- encoding/payloads/cert_payload.c \
- encoding/payloads/cert_payload.h \
- encoding/payloads/certreq_payload.c \
- encoding/payloads/certreq_payload.h \
- encoding/payloads/configuration_attribute.c \
- encoding/payloads/configuration_attribute.h \
- encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
- encoding/payloads/delete_payload.c \
- encoding/payloads/delete_payload.h \
- encoding/payloads/eap_payload.c \
- encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
- encoding/payloads/encodings.h \
- encoding/payloads/encryption_payload.c \
- encoding/payloads/encryption_payload.h \
- encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
- encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
- encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
- encoding/payloads/nonce_payload.c \
- encoding/payloads/nonce_payload.h \
- encoding/payloads/notify_payload.c \
- encoding/payloads/notify_payload.h encoding/payloads/payload.c \
- encoding/payloads/payload.h \
- encoding/payloads/proposal_substructure.c \
- encoding/payloads/proposal_substructure.h \
- encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
- encoding/payloads/traffic_selector_substructure.c \
- encoding/payloads/traffic_selector_substructure.h \
- encoding/payloads/transform_attribute.c \
- encoding/payloads/transform_attribute.h \
- encoding/payloads/transform_substructure.c \
- encoding/payloads/transform_substructure.h \
- encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
- encoding/payloads/unknown_payload.c \
- encoding/payloads/unknown_payload.h \
- encoding/payloads/vendor_id_payload.c \
- encoding/payloads/vendor_id_payload.h \
- kernel/kernel_interface.c kernel/kernel_interface.h \
- kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
- kernel/kernel_net.h network/packet.c network/packet.h \
- network/receiver.c network/receiver.h network/sender.c \
- network/sender.h network/socket.h processing/jobs/job.h \
- processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
- processing/jobs/callback_job.c processing/jobs/callback_job.h \
- processing/jobs/delete_child_sa_job.c \
- processing/jobs/delete_child_sa_job.h \
- processing/jobs/delete_ike_sa_job.c \
- processing/jobs/delete_ike_sa_job.h \
- processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
- processing/jobs/process_message_job.c \
- processing/jobs/process_message_job.h \
- processing/jobs/rekey_child_sa_job.c \
- processing/jobs/rekey_child_sa_job.h \
- processing/jobs/rekey_ike_sa_job.c \
- processing/jobs/rekey_ike_sa_job.h \
- processing/jobs/retransmit_job.c \
- processing/jobs/retransmit_job.h \
- processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
- processing/jobs/send_keepalive_job.c \
- processing/jobs/send_keepalive_job.h \
- processing/jobs/roam_job.c processing/jobs/roam_job.h \
- processing/jobs/update_sa_job.c \
- processing/jobs/update_sa_job.h \
- processing/jobs/inactivity_job.c \
- processing/jobs/inactivity_job.h processing/scheduler.c \
- processing/scheduler.h processing/processor.c \
- processing/processor.h sa/authenticators/authenticator.c \
- sa/authenticators/authenticator.h \
- sa/authenticators/eap_authenticator.c \
- sa/authenticators/eap_authenticator.h \
- sa/authenticators/eap/eap_method.c \
- sa/authenticators/eap/eap_method.h \
- sa/authenticators/eap/eap_manager.c \
- sa/authenticators/eap/eap_manager.h \
- sa/authenticators/eap/sim_manager.c \
- sa/authenticators/eap/sim_manager.h \
- sa/authenticators/psk_authenticator.c \
- sa/authenticators/psk_authenticator.h \
- sa/authenticators/pubkey_authenticator.c \
- sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
- sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
- sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
- sa/trap_manager.c sa/trap_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
- sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
- sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
- sa/tasks/ike_config.c sa/tasks/ike_config.h \
- sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
- sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
- sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
- sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
- sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
- sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
- sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
- sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- credentials/credential_manager.c \
- credentials/credential_manager.h \
- credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
- credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/credential_set.h network/socket-raw.c \
- network/socket.c encoding/payloads/endpoint_notify.c \
- encoding/payloads/endpoint_notify.h \
- processing/jobs/initiate_mediation_job.c \
- processing/jobs/initiate_mediation_job.h \
- processing/jobs/mediation_job.c \
- processing/jobs/mediation_job.h sa/connect_manager.c \
- sa/connect_manager.h sa/mediation_manager.c \
- sa/mediation_manager.h sa/tasks/ike_me.c sa/tasks/ike_me.h
-@USE_PLUTO_TRUE@am__objects_1 = socket-raw.$(OBJEXT)
-@USE_PLUTO_FALSE@am__objects_2 = socket.$(OBJEXT)
-@USE_ME_TRUE@am__objects_3 = endpoint_notify.$(OBJEXT) \
-@USE_ME_TRUE@ initiate_mediation_job.$(OBJEXT) \
-@USE_ME_TRUE@ mediation_job.$(OBJEXT) connect_manager.$(OBJEXT) \
-@USE_ME_TRUE@ mediation_manager.$(OBJEXT) ike_me.$(OBJEXT)
-am_charon_OBJECTS = bus.$(OBJEXT) file_logger.$(OBJEXT) \
- sys_logger.$(OBJEXT) backend_manager.$(OBJEXT) \
- child_cfg.$(OBJEXT) ike_cfg.$(OBJEXT) peer_cfg.$(OBJEXT) \
- proposal.$(OBJEXT) auth_cfg.$(OBJEXT) controller.$(OBJEXT) \
- daemon.$(OBJEXT) generator.$(OBJEXT) message.$(OBJEXT) \
- parser.$(OBJEXT) auth_payload.$(OBJEXT) cert_payload.$(OBJEXT) \
- certreq_payload.$(OBJEXT) configuration_attribute.$(OBJEXT) \
- cp_payload.$(OBJEXT) delete_payload.$(OBJEXT) \
- eap_payload.$(OBJEXT) encodings.$(OBJEXT) \
- encryption_payload.$(OBJEXT) id_payload.$(OBJEXT) \
- ike_header.$(OBJEXT) ke_payload.$(OBJEXT) \
- nonce_payload.$(OBJEXT) notify_payload.$(OBJEXT) \
- payload.$(OBJEXT) proposal_substructure.$(OBJEXT) \
- sa_payload.$(OBJEXT) traffic_selector_substructure.$(OBJEXT) \
- transform_attribute.$(OBJEXT) transform_substructure.$(OBJEXT) \
- ts_payload.$(OBJEXT) unknown_payload.$(OBJEXT) \
- vendor_id_payload.$(OBJEXT) kernel_interface.$(OBJEXT) \
- kernel_ipsec.$(OBJEXT) packet.$(OBJEXT) receiver.$(OBJEXT) \
- sender.$(OBJEXT) acquire_job.$(OBJEXT) callback_job.$(OBJEXT) \
- delete_child_sa_job.$(OBJEXT) delete_ike_sa_job.$(OBJEXT) \
- migrate_job.$(OBJEXT) process_message_job.$(OBJEXT) \
- rekey_child_sa_job.$(OBJEXT) rekey_ike_sa_job.$(OBJEXT) \
- retransmit_job.$(OBJEXT) send_dpd_job.$(OBJEXT) \
- send_keepalive_job.$(OBJEXT) roam_job.$(OBJEXT) \
- update_sa_job.$(OBJEXT) inactivity_job.$(OBJEXT) \
- scheduler.$(OBJEXT) processor.$(OBJEXT) \
- authenticator.$(OBJEXT) eap_authenticator.$(OBJEXT) \
- eap_method.$(OBJEXT) eap_manager.$(OBJEXT) \
- sim_manager.$(OBJEXT) psk_authenticator.$(OBJEXT) \
- pubkey_authenticator.$(OBJEXT) child_sa.$(OBJEXT) \
- ike_sa.$(OBJEXT) ike_sa_id.$(OBJEXT) ike_sa_manager.$(OBJEXT) \
- task_manager.$(OBJEXT) keymat.$(OBJEXT) trap_manager.$(OBJEXT) \
- child_create.$(OBJEXT) child_delete.$(OBJEXT) \
- child_rekey.$(OBJEXT) ike_auth.$(OBJEXT) \
- ike_cert_pre.$(OBJEXT) ike_cert_post.$(OBJEXT) \
- ike_config.$(OBJEXT) ike_delete.$(OBJEXT) ike_dpd.$(OBJEXT) \
- ike_init.$(OBJEXT) ike_natd.$(OBJEXT) ike_mobike.$(OBJEXT) \
- ike_rekey.$(OBJEXT) ike_reauth.$(OBJEXT) \
- ike_auth_lifetime.$(OBJEXT) ike_vendor.$(OBJEXT) \
- task.$(OBJEXT) credential_manager.$(OBJEXT) \
- auth_cfg_wrapper.$(OBJEXT) ocsp_response_wrapper.$(OBJEXT) \
- cert_cache.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
- $(am__objects_3)
+am_charon_OBJECTS = charon.$(OBJEXT)
charon_OBJECTS = $(am_charon_OBJECTS)
am__DEPENDENCIES_1 =
charon_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -317,57 +75,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(charon_SOURCES)
-DIST_SOURCES = $(am__charon_SOURCES_DIST)
-RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
- $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
- distdir
+DIST_SOURCES = $(charon_SOURCES)
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = . plugins/load_tester plugins/kernel_pfkey \
- plugins/kernel_pfroute plugins/kernel_klips \
- plugins/kernel_netlink plugins/stroke plugins/smp plugins/sql \
- plugins/updown plugins/attr plugins/eap_identity \
- plugins/eap_sim plugins/eap_sim_file \
- plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
- plugins/eap_md5 plugins/eap_gtc plugins/eap_aka \
- plugins/eap_aka_3gpp2 plugins/eap_mschapv2 plugins/eap_radius \
- plugins/medsrv plugins/medcli plugins/nm plugins/resolve \
- plugins/uci plugins/unit_tester
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@
@@ -488,6 +199,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -522,153 +234,26 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-charon_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.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 \
- config/peer_cfg.h config/proposal.c config/proposal.h \
- config/auth_cfg.c config/auth_cfg.h control/controller.c \
- control/controller.h daemon.c daemon.h encoding/generator.c \
- encoding/generator.h encoding/message.c encoding/message.h \
- encoding/parser.c encoding/parser.h \
- encoding/payloads/auth_payload.c \
- encoding/payloads/auth_payload.h \
- encoding/payloads/cert_payload.c \
- encoding/payloads/cert_payload.h \
- encoding/payloads/certreq_payload.c \
- encoding/payloads/certreq_payload.h \
- encoding/payloads/configuration_attribute.c \
- encoding/payloads/configuration_attribute.h \
- encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
- encoding/payloads/delete_payload.c \
- encoding/payloads/delete_payload.h \
- encoding/payloads/eap_payload.c \
- encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
- encoding/payloads/encodings.h \
- encoding/payloads/encryption_payload.c \
- encoding/payloads/encryption_payload.h \
- encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
- encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
- encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
- encoding/payloads/nonce_payload.c \
- encoding/payloads/nonce_payload.h \
- encoding/payloads/notify_payload.c \
- encoding/payloads/notify_payload.h encoding/payloads/payload.c \
- encoding/payloads/payload.h \
- encoding/payloads/proposal_substructure.c \
- encoding/payloads/proposal_substructure.h \
- encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
- encoding/payloads/traffic_selector_substructure.c \
- encoding/payloads/traffic_selector_substructure.h \
- encoding/payloads/transform_attribute.c \
- encoding/payloads/transform_attribute.h \
- encoding/payloads/transform_substructure.c \
- encoding/payloads/transform_substructure.h \
- encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
- encoding/payloads/unknown_payload.c \
- encoding/payloads/unknown_payload.h \
- encoding/payloads/vendor_id_payload.c \
- encoding/payloads/vendor_id_payload.h \
- kernel/kernel_interface.c kernel/kernel_interface.h \
- kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
- kernel/kernel_net.h network/packet.c network/packet.h \
- network/receiver.c network/receiver.h network/sender.c \
- network/sender.h network/socket.h processing/jobs/job.h \
- processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
- processing/jobs/callback_job.c processing/jobs/callback_job.h \
- processing/jobs/delete_child_sa_job.c \
- processing/jobs/delete_child_sa_job.h \
- processing/jobs/delete_ike_sa_job.c \
- processing/jobs/delete_ike_sa_job.h \
- processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
- processing/jobs/process_message_job.c \
- processing/jobs/process_message_job.h \
- processing/jobs/rekey_child_sa_job.c \
- processing/jobs/rekey_child_sa_job.h \
- processing/jobs/rekey_ike_sa_job.c \
- processing/jobs/rekey_ike_sa_job.h \
- processing/jobs/retransmit_job.c \
- processing/jobs/retransmit_job.h \
- processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
- processing/jobs/send_keepalive_job.c \
- processing/jobs/send_keepalive_job.h \
- processing/jobs/roam_job.c processing/jobs/roam_job.h \
- processing/jobs/update_sa_job.c \
- processing/jobs/update_sa_job.h \
- processing/jobs/inactivity_job.c \
- processing/jobs/inactivity_job.h processing/scheduler.c \
- processing/scheduler.h processing/processor.c \
- processing/processor.h sa/authenticators/authenticator.c \
- sa/authenticators/authenticator.h \
- sa/authenticators/eap_authenticator.c \
- sa/authenticators/eap_authenticator.h \
- sa/authenticators/eap/eap_method.c \
- sa/authenticators/eap/eap_method.h \
- sa/authenticators/eap/eap_manager.c \
- sa/authenticators/eap/eap_manager.h \
- sa/authenticators/eap/sim_manager.c \
- sa/authenticators/eap/sim_manager.h \
- sa/authenticators/psk_authenticator.c \
- sa/authenticators/psk_authenticator.h \
- sa/authenticators/pubkey_authenticator.c \
- sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
- sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
- sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
- sa/trap_manager.c sa/trap_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
- sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
- sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
- sa/tasks/ike_config.c sa/tasks/ike_config.h \
- sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
- sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
- sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
- sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
- sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
- sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
- sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
- sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- credentials/credential_manager.c \
- credentials/credential_manager.h \
- credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
- credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/credential_set.h $(am__append_1) $(am__append_2) \
- $(am__append_3)
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
-AM_CFLAGS = -rdynamic -DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\" -DPLUGINS=\""${PLUGINS}\""
-charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lm \
- $(PTHREADLIB) $(DLLIB) $(SOCKLIB) $(am__append_4)
-
-# build optional plugins
-########################
-SUBDIRS = . $(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_43) $(am__append_45) \
- $(am__append_47) $(am__append_49) $(am__append_51) \
- $(am__append_53) $(am__append_55) $(am__append_57)
-PLUGINS = ${libstrongswan_plugins} $(am__append_6) $(am__append_8) \
- $(am__append_10) $(am__append_12) $(am__append_14) \
- $(am__append_16) $(am__append_18) $(am__append_20) \
- $(am__append_22) $(am__append_24) $(am__append_26) \
- $(am__append_28) $(am__append_30) $(am__append_32) \
- $(am__append_34) $(am__append_36) $(am__append_38) \
- $(am__append_40) $(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)
-all: all-recursive
+charon_SOURCES = \
+charon.c
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_PIDDIR=\"${piddir}\"
+
+charon_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ -lm $(PTHREADLIB) $(DLLIB)
+
+EXTRA_DIST = Android.mk
+all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@@ -755,107 +340,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg_wrapper.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certreq_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_cfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_create.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_delete.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_rekey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_sa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration_attribute.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_authenticator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_method.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryption_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/endpoint_notify.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_logger.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/id_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth_lifetime.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_post.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_pre.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_config.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_delete.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_dpd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_header.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_init.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_me.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_mobike.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_natd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_reauth.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_rekey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_id.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_vendor.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inactivity_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_interface.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_ipsec.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer_cfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_message_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processor.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_substructure.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_authenticator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey_authenticator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_child_sa_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_ike_sa_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retransmit_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roam_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sa_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_dpd_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_keepalive_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket-raw.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_logger.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector_substructure.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_attribute.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_substructure.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trap_manager.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ts_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unknown_payload.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update_sa_job.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor_id_payload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charon.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -878,1482 +363,12 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-bus.o: bus/bus.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bus.o -MD -MP -MF $(DEPDIR)/bus.Tpo -c -o bus.o `test -f 'bus/bus.c' || echo '$(srcdir)/'`bus/bus.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bus.Tpo $(DEPDIR)/bus.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/bus.c' object='bus.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bus.o `test -f 'bus/bus.c' || echo '$(srcdir)/'`bus/bus.c
-
-bus.obj: bus/bus.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bus.obj -MD -MP -MF $(DEPDIR)/bus.Tpo -c -o bus.obj `if test -f 'bus/bus.c'; then $(CYGPATH_W) 'bus/bus.c'; else $(CYGPATH_W) '$(srcdir)/bus/bus.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bus.Tpo $(DEPDIR)/bus.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/bus.c' object='bus.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bus.obj `if test -f 'bus/bus.c'; then $(CYGPATH_W) 'bus/bus.c'; else $(CYGPATH_W) '$(srcdir)/bus/bus.c'; fi`
-
-file_logger.o: bus/listeners/file_logger.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_logger.o -MD -MP -MF $(DEPDIR)/file_logger.Tpo -c -o file_logger.o `test -f 'bus/listeners/file_logger.c' || echo '$(srcdir)/'`bus/listeners/file_logger.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/file_logger.Tpo $(DEPDIR)/file_logger.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/file_logger.c' object='file_logger.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_logger.o `test -f 'bus/listeners/file_logger.c' || echo '$(srcdir)/'`bus/listeners/file_logger.c
-
-file_logger.obj: bus/listeners/file_logger.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_logger.obj -MD -MP -MF $(DEPDIR)/file_logger.Tpo -c -o file_logger.obj `if test -f 'bus/listeners/file_logger.c'; then $(CYGPATH_W) 'bus/listeners/file_logger.c'; else $(CYGPATH_W) '$(srcdir)/bus/listeners/file_logger.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/file_logger.Tpo $(DEPDIR)/file_logger.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/file_logger.c' object='file_logger.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_logger.obj `if test -f 'bus/listeners/file_logger.c'; then $(CYGPATH_W) 'bus/listeners/file_logger.c'; else $(CYGPATH_W) '$(srcdir)/bus/listeners/file_logger.c'; fi`
-
-sys_logger.o: bus/listeners/sys_logger.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sys_logger.o -MD -MP -MF $(DEPDIR)/sys_logger.Tpo -c -o sys_logger.o `test -f 'bus/listeners/sys_logger.c' || echo '$(srcdir)/'`bus/listeners/sys_logger.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sys_logger.Tpo $(DEPDIR)/sys_logger.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/sys_logger.c' object='sys_logger.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sys_logger.o `test -f 'bus/listeners/sys_logger.c' || echo '$(srcdir)/'`bus/listeners/sys_logger.c
-
-sys_logger.obj: bus/listeners/sys_logger.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sys_logger.obj -MD -MP -MF $(DEPDIR)/sys_logger.Tpo -c -o sys_logger.obj `if test -f 'bus/listeners/sys_logger.c'; then $(CYGPATH_W) 'bus/listeners/sys_logger.c'; else $(CYGPATH_W) '$(srcdir)/bus/listeners/sys_logger.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sys_logger.Tpo $(DEPDIR)/sys_logger.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/sys_logger.c' object='sys_logger.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sys_logger.obj `if test -f 'bus/listeners/sys_logger.c'; then $(CYGPATH_W) 'bus/listeners/sys_logger.c'; else $(CYGPATH_W) '$(srcdir)/bus/listeners/sys_logger.c'; fi`
-
-backend_manager.o: config/backend_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_manager.o -MD -MP -MF $(DEPDIR)/backend_manager.Tpo -c -o backend_manager.o `test -f 'config/backend_manager.c' || echo '$(srcdir)/'`config/backend_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/backend_manager.Tpo $(DEPDIR)/backend_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/backend_manager.c' object='backend_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_manager.o `test -f 'config/backend_manager.c' || echo '$(srcdir)/'`config/backend_manager.c
-
-backend_manager.obj: config/backend_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_manager.obj -MD -MP -MF $(DEPDIR)/backend_manager.Tpo -c -o backend_manager.obj `if test -f 'config/backend_manager.c'; then $(CYGPATH_W) 'config/backend_manager.c'; else $(CYGPATH_W) '$(srcdir)/config/backend_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/backend_manager.Tpo $(DEPDIR)/backend_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/backend_manager.c' object='backend_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_manager.obj `if test -f 'config/backend_manager.c'; then $(CYGPATH_W) 'config/backend_manager.c'; else $(CYGPATH_W) '$(srcdir)/config/backend_manager.c'; fi`
-
-child_cfg.o: config/child_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_cfg.o -MD -MP -MF $(DEPDIR)/child_cfg.Tpo -c -o child_cfg.o `test -f 'config/child_cfg.c' || echo '$(srcdir)/'`config/child_cfg.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_cfg.Tpo $(DEPDIR)/child_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/child_cfg.c' object='child_cfg.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_cfg.o `test -f 'config/child_cfg.c' || echo '$(srcdir)/'`config/child_cfg.c
-
-child_cfg.obj: config/child_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_cfg.obj -MD -MP -MF $(DEPDIR)/child_cfg.Tpo -c -o child_cfg.obj `if test -f 'config/child_cfg.c'; then $(CYGPATH_W) 'config/child_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/child_cfg.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_cfg.Tpo $(DEPDIR)/child_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/child_cfg.c' object='child_cfg.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_cfg.obj `if test -f 'config/child_cfg.c'; then $(CYGPATH_W) 'config/child_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/child_cfg.c'; fi`
-
-ike_cfg.o: config/ike_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cfg.o -MD -MP -MF $(DEPDIR)/ike_cfg.Tpo -c -o ike_cfg.o `test -f 'config/ike_cfg.c' || echo '$(srcdir)/'`config/ike_cfg.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cfg.Tpo $(DEPDIR)/ike_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/ike_cfg.c' object='ike_cfg.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cfg.o `test -f 'config/ike_cfg.c' || echo '$(srcdir)/'`config/ike_cfg.c
-
-ike_cfg.obj: config/ike_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cfg.obj -MD -MP -MF $(DEPDIR)/ike_cfg.Tpo -c -o ike_cfg.obj `if test -f 'config/ike_cfg.c'; then $(CYGPATH_W) 'config/ike_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/ike_cfg.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cfg.Tpo $(DEPDIR)/ike_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/ike_cfg.c' object='ike_cfg.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cfg.obj `if test -f 'config/ike_cfg.c'; then $(CYGPATH_W) 'config/ike_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/ike_cfg.c'; fi`
-
-peer_cfg.o: config/peer_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT peer_cfg.o -MD -MP -MF $(DEPDIR)/peer_cfg.Tpo -c -o peer_cfg.o `test -f 'config/peer_cfg.c' || echo '$(srcdir)/'`config/peer_cfg.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/peer_cfg.Tpo $(DEPDIR)/peer_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/peer_cfg.c' object='peer_cfg.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o peer_cfg.o `test -f 'config/peer_cfg.c' || echo '$(srcdir)/'`config/peer_cfg.c
-
-peer_cfg.obj: config/peer_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT peer_cfg.obj -MD -MP -MF $(DEPDIR)/peer_cfg.Tpo -c -o peer_cfg.obj `if test -f 'config/peer_cfg.c'; then $(CYGPATH_W) 'config/peer_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/peer_cfg.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/peer_cfg.Tpo $(DEPDIR)/peer_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/peer_cfg.c' object='peer_cfg.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o peer_cfg.obj `if test -f 'config/peer_cfg.c'; then $(CYGPATH_W) 'config/peer_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/peer_cfg.c'; fi`
-
-proposal.o: config/proposal.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal.o -MD -MP -MF $(DEPDIR)/proposal.Tpo -c -o proposal.o `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal.Tpo $(DEPDIR)/proposal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/proposal.c' object='proposal.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal.o `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c
-
-proposal.obj: config/proposal.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal.obj -MD -MP -MF $(DEPDIR)/proposal.Tpo -c -o proposal.obj `if test -f 'config/proposal.c'; then $(CYGPATH_W) 'config/proposal.c'; else $(CYGPATH_W) '$(srcdir)/config/proposal.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal.Tpo $(DEPDIR)/proposal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/proposal.c' object='proposal.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal.obj `if test -f 'config/proposal.c'; then $(CYGPATH_W) 'config/proposal.c'; else $(CYGPATH_W) '$(srcdir)/config/proposal.c'; fi`
-
-auth_cfg.o: config/auth_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.o -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.o `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/auth_cfg.c' object='auth_cfg.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg.o `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
-
-auth_cfg.obj: config/auth_cfg.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.obj -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.obj `if test -f 'config/auth_cfg.c'; then $(CYGPATH_W) 'config/auth_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/auth_cfg.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/auth_cfg.c' object='auth_cfg.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg.obj `if test -f 'config/auth_cfg.c'; then $(CYGPATH_W) 'config/auth_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/auth_cfg.c'; fi`
-
-controller.o: control/controller.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.o -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.o `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/controller.c' object='controller.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o controller.o `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c
-
-controller.obj: control/controller.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.obj -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.obj `if test -f 'control/controller.c'; then $(CYGPATH_W) 'control/controller.c'; else $(CYGPATH_W) '$(srcdir)/control/controller.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/controller.c' object='controller.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o controller.obj `if test -f 'control/controller.c'; then $(CYGPATH_W) 'control/controller.c'; else $(CYGPATH_W) '$(srcdir)/control/controller.c'; fi`
-
-generator.o: encoding/generator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT generator.o -MD -MP -MF $(DEPDIR)/generator.Tpo -c -o generator.o `test -f 'encoding/generator.c' || echo '$(srcdir)/'`encoding/generator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generator.Tpo $(DEPDIR)/generator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/generator.c' object='generator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o generator.o `test -f 'encoding/generator.c' || echo '$(srcdir)/'`encoding/generator.c
-
-generator.obj: encoding/generator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT generator.obj -MD -MP -MF $(DEPDIR)/generator.Tpo -c -o generator.obj `if test -f 'encoding/generator.c'; then $(CYGPATH_W) 'encoding/generator.c'; else $(CYGPATH_W) '$(srcdir)/encoding/generator.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generator.Tpo $(DEPDIR)/generator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/generator.c' object='generator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o generator.obj `if test -f 'encoding/generator.c'; then $(CYGPATH_W) 'encoding/generator.c'; else $(CYGPATH_W) '$(srcdir)/encoding/generator.c'; fi`
-
-message.o: encoding/message.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT message.o -MD -MP -MF $(DEPDIR)/message.Tpo -c -o message.o `test -f 'encoding/message.c' || echo '$(srcdir)/'`encoding/message.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/message.Tpo $(DEPDIR)/message.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/message.c' object='message.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o message.o `test -f 'encoding/message.c' || echo '$(srcdir)/'`encoding/message.c
-
-message.obj: encoding/message.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT message.obj -MD -MP -MF $(DEPDIR)/message.Tpo -c -o message.obj `if test -f 'encoding/message.c'; then $(CYGPATH_W) 'encoding/message.c'; else $(CYGPATH_W) '$(srcdir)/encoding/message.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/message.Tpo $(DEPDIR)/message.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/message.c' object='message.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o message.obj `if test -f 'encoding/message.c'; then $(CYGPATH_W) 'encoding/message.c'; else $(CYGPATH_W) '$(srcdir)/encoding/message.c'; fi`
-
-parser.o: encoding/parser.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser.o -MD -MP -MF $(DEPDIR)/parser.Tpo -c -o parser.o `test -f 'encoding/parser.c' || echo '$(srcdir)/'`encoding/parser.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser.Tpo $(DEPDIR)/parser.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/parser.c' object='parser.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser.o `test -f 'encoding/parser.c' || echo '$(srcdir)/'`encoding/parser.c
-
-parser.obj: encoding/parser.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser.obj -MD -MP -MF $(DEPDIR)/parser.Tpo -c -o parser.obj `if test -f 'encoding/parser.c'; then $(CYGPATH_W) 'encoding/parser.c'; else $(CYGPATH_W) '$(srcdir)/encoding/parser.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser.Tpo $(DEPDIR)/parser.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/parser.c' object='parser.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser.obj `if test -f 'encoding/parser.c'; then $(CYGPATH_W) 'encoding/parser.c'; else $(CYGPATH_W) '$(srcdir)/encoding/parser.c'; fi`
-
-auth_payload.o: encoding/payloads/auth_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_payload.o -MD -MP -MF $(DEPDIR)/auth_payload.Tpo -c -o auth_payload.o `test -f 'encoding/payloads/auth_payload.c' || echo '$(srcdir)/'`encoding/payloads/auth_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_payload.Tpo $(DEPDIR)/auth_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/auth_payload.c' object='auth_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_payload.o `test -f 'encoding/payloads/auth_payload.c' || echo '$(srcdir)/'`encoding/payloads/auth_payload.c
-
-auth_payload.obj: encoding/payloads/auth_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_payload.obj -MD -MP -MF $(DEPDIR)/auth_payload.Tpo -c -o auth_payload.obj `if test -f 'encoding/payloads/auth_payload.c'; then $(CYGPATH_W) 'encoding/payloads/auth_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/auth_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_payload.Tpo $(DEPDIR)/auth_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/auth_payload.c' object='auth_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_payload.obj `if test -f 'encoding/payloads/auth_payload.c'; then $(CYGPATH_W) 'encoding/payloads/auth_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/auth_payload.c'; fi`
-
-cert_payload.o: encoding/payloads/cert_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_payload.o -MD -MP -MF $(DEPDIR)/cert_payload.Tpo -c -o cert_payload.o `test -f 'encoding/payloads/cert_payload.c' || echo '$(srcdir)/'`encoding/payloads/cert_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_payload.Tpo $(DEPDIR)/cert_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cert_payload.c' object='cert_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_payload.o `test -f 'encoding/payloads/cert_payload.c' || echo '$(srcdir)/'`encoding/payloads/cert_payload.c
-
-cert_payload.obj: encoding/payloads/cert_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_payload.obj -MD -MP -MF $(DEPDIR)/cert_payload.Tpo -c -o cert_payload.obj `if test -f 'encoding/payloads/cert_payload.c'; then $(CYGPATH_W) 'encoding/payloads/cert_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/cert_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_payload.Tpo $(DEPDIR)/cert_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cert_payload.c' object='cert_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_payload.obj `if test -f 'encoding/payloads/cert_payload.c'; then $(CYGPATH_W) 'encoding/payloads/cert_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/cert_payload.c'; fi`
-
-certreq_payload.o: encoding/payloads/certreq_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT certreq_payload.o -MD -MP -MF $(DEPDIR)/certreq_payload.Tpo -c -o certreq_payload.o `test -f 'encoding/payloads/certreq_payload.c' || echo '$(srcdir)/'`encoding/payloads/certreq_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/certreq_payload.Tpo $(DEPDIR)/certreq_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/certreq_payload.c' object='certreq_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o certreq_payload.o `test -f 'encoding/payloads/certreq_payload.c' || echo '$(srcdir)/'`encoding/payloads/certreq_payload.c
-
-certreq_payload.obj: encoding/payloads/certreq_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT certreq_payload.obj -MD -MP -MF $(DEPDIR)/certreq_payload.Tpo -c -o certreq_payload.obj `if test -f 'encoding/payloads/certreq_payload.c'; then $(CYGPATH_W) 'encoding/payloads/certreq_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/certreq_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/certreq_payload.Tpo $(DEPDIR)/certreq_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/certreq_payload.c' object='certreq_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o certreq_payload.obj `if test -f 'encoding/payloads/certreq_payload.c'; then $(CYGPATH_W) 'encoding/payloads/certreq_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/certreq_payload.c'; fi`
-
-configuration_attribute.o: encoding/payloads/configuration_attribute.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT configuration_attribute.o -MD -MP -MF $(DEPDIR)/configuration_attribute.Tpo -c -o configuration_attribute.o `test -f 'encoding/payloads/configuration_attribute.c' || echo '$(srcdir)/'`encoding/payloads/configuration_attribute.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/configuration_attribute.Tpo $(DEPDIR)/configuration_attribute.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/configuration_attribute.c' object='configuration_attribute.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o configuration_attribute.o `test -f 'encoding/payloads/configuration_attribute.c' || echo '$(srcdir)/'`encoding/payloads/configuration_attribute.c
-
-configuration_attribute.obj: encoding/payloads/configuration_attribute.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT configuration_attribute.obj -MD -MP -MF $(DEPDIR)/configuration_attribute.Tpo -c -o configuration_attribute.obj `if test -f 'encoding/payloads/configuration_attribute.c'; then $(CYGPATH_W) 'encoding/payloads/configuration_attribute.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/configuration_attribute.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/configuration_attribute.Tpo $(DEPDIR)/configuration_attribute.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/configuration_attribute.c' object='configuration_attribute.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o configuration_attribute.obj `if test -f 'encoding/payloads/configuration_attribute.c'; then $(CYGPATH_W) 'encoding/payloads/configuration_attribute.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/configuration_attribute.c'; fi`
-
-cp_payload.o: encoding/payloads/cp_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cp_payload.o -MD -MP -MF $(DEPDIR)/cp_payload.Tpo -c -o cp_payload.o `test -f 'encoding/payloads/cp_payload.c' || echo '$(srcdir)/'`encoding/payloads/cp_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cp_payload.Tpo $(DEPDIR)/cp_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cp_payload.c' object='cp_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cp_payload.o `test -f 'encoding/payloads/cp_payload.c' || echo '$(srcdir)/'`encoding/payloads/cp_payload.c
-
-cp_payload.obj: encoding/payloads/cp_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cp_payload.obj -MD -MP -MF $(DEPDIR)/cp_payload.Tpo -c -o cp_payload.obj `if test -f 'encoding/payloads/cp_payload.c'; then $(CYGPATH_W) 'encoding/payloads/cp_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/cp_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cp_payload.Tpo $(DEPDIR)/cp_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cp_payload.c' object='cp_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cp_payload.obj `if test -f 'encoding/payloads/cp_payload.c'; then $(CYGPATH_W) 'encoding/payloads/cp_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/cp_payload.c'; fi`
-
-delete_payload.o: encoding/payloads/delete_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_payload.o -MD -MP -MF $(DEPDIR)/delete_payload.Tpo -c -o delete_payload.o `test -f 'encoding/payloads/delete_payload.c' || echo '$(srcdir)/'`encoding/payloads/delete_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_payload.Tpo $(DEPDIR)/delete_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/delete_payload.c' object='delete_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_payload.o `test -f 'encoding/payloads/delete_payload.c' || echo '$(srcdir)/'`encoding/payloads/delete_payload.c
-
-delete_payload.obj: encoding/payloads/delete_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_payload.obj -MD -MP -MF $(DEPDIR)/delete_payload.Tpo -c -o delete_payload.obj `if test -f 'encoding/payloads/delete_payload.c'; then $(CYGPATH_W) 'encoding/payloads/delete_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/delete_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_payload.Tpo $(DEPDIR)/delete_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/delete_payload.c' object='delete_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_payload.obj `if test -f 'encoding/payloads/delete_payload.c'; then $(CYGPATH_W) 'encoding/payloads/delete_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/delete_payload.c'; fi`
-
-eap_payload.o: encoding/payloads/eap_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_payload.o -MD -MP -MF $(DEPDIR)/eap_payload.Tpo -c -o eap_payload.o `test -f 'encoding/payloads/eap_payload.c' || echo '$(srcdir)/'`encoding/payloads/eap_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_payload.Tpo $(DEPDIR)/eap_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/eap_payload.c' object='eap_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_payload.o `test -f 'encoding/payloads/eap_payload.c' || echo '$(srcdir)/'`encoding/payloads/eap_payload.c
-
-eap_payload.obj: encoding/payloads/eap_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_payload.obj -MD -MP -MF $(DEPDIR)/eap_payload.Tpo -c -o eap_payload.obj `if test -f 'encoding/payloads/eap_payload.c'; then $(CYGPATH_W) 'encoding/payloads/eap_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/eap_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_payload.Tpo $(DEPDIR)/eap_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/eap_payload.c' object='eap_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_payload.obj `if test -f 'encoding/payloads/eap_payload.c'; then $(CYGPATH_W) 'encoding/payloads/eap_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/eap_payload.c'; fi`
-
-encodings.o: encoding/payloads/encodings.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encodings.o -MD -MP -MF $(DEPDIR)/encodings.Tpo -c -o encodings.o `test -f 'encoding/payloads/encodings.c' || echo '$(srcdir)/'`encoding/payloads/encodings.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encodings.Tpo $(DEPDIR)/encodings.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encodings.c' object='encodings.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encodings.o `test -f 'encoding/payloads/encodings.c' || echo '$(srcdir)/'`encoding/payloads/encodings.c
-
-encodings.obj: encoding/payloads/encodings.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encodings.obj -MD -MP -MF $(DEPDIR)/encodings.Tpo -c -o encodings.obj `if test -f 'encoding/payloads/encodings.c'; then $(CYGPATH_W) 'encoding/payloads/encodings.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/encodings.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encodings.Tpo $(DEPDIR)/encodings.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encodings.c' object='encodings.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encodings.obj `if test -f 'encoding/payloads/encodings.c'; then $(CYGPATH_W) 'encoding/payloads/encodings.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/encodings.c'; fi`
-
-encryption_payload.o: encoding/payloads/encryption_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encryption_payload.o -MD -MP -MF $(DEPDIR)/encryption_payload.Tpo -c -o encryption_payload.o `test -f 'encoding/payloads/encryption_payload.c' || echo '$(srcdir)/'`encoding/payloads/encryption_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encryption_payload.Tpo $(DEPDIR)/encryption_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encryption_payload.c' object='encryption_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encryption_payload.o `test -f 'encoding/payloads/encryption_payload.c' || echo '$(srcdir)/'`encoding/payloads/encryption_payload.c
-
-encryption_payload.obj: encoding/payloads/encryption_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encryption_payload.obj -MD -MP -MF $(DEPDIR)/encryption_payload.Tpo -c -o encryption_payload.obj `if test -f 'encoding/payloads/encryption_payload.c'; then $(CYGPATH_W) 'encoding/payloads/encryption_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/encryption_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encryption_payload.Tpo $(DEPDIR)/encryption_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encryption_payload.c' object='encryption_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encryption_payload.obj `if test -f 'encoding/payloads/encryption_payload.c'; then $(CYGPATH_W) 'encoding/payloads/encryption_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/encryption_payload.c'; fi`
-
-id_payload.o: encoding/payloads/id_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT id_payload.o -MD -MP -MF $(DEPDIR)/id_payload.Tpo -c -o id_payload.o `test -f 'encoding/payloads/id_payload.c' || echo '$(srcdir)/'`encoding/payloads/id_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/id_payload.Tpo $(DEPDIR)/id_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/id_payload.c' object='id_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o id_payload.o `test -f 'encoding/payloads/id_payload.c' || echo '$(srcdir)/'`encoding/payloads/id_payload.c
-
-id_payload.obj: encoding/payloads/id_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT id_payload.obj -MD -MP -MF $(DEPDIR)/id_payload.Tpo -c -o id_payload.obj `if test -f 'encoding/payloads/id_payload.c'; then $(CYGPATH_W) 'encoding/payloads/id_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/id_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/id_payload.Tpo $(DEPDIR)/id_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/id_payload.c' object='id_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o id_payload.obj `if test -f 'encoding/payloads/id_payload.c'; then $(CYGPATH_W) 'encoding/payloads/id_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/id_payload.c'; fi`
-
-ike_header.o: encoding/payloads/ike_header.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_header.o -MD -MP -MF $(DEPDIR)/ike_header.Tpo -c -o ike_header.o `test -f 'encoding/payloads/ike_header.c' || echo '$(srcdir)/'`encoding/payloads/ike_header.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_header.Tpo $(DEPDIR)/ike_header.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ike_header.c' object='ike_header.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_header.o `test -f 'encoding/payloads/ike_header.c' || echo '$(srcdir)/'`encoding/payloads/ike_header.c
-
-ike_header.obj: encoding/payloads/ike_header.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_header.obj -MD -MP -MF $(DEPDIR)/ike_header.Tpo -c -o ike_header.obj `if test -f 'encoding/payloads/ike_header.c'; then $(CYGPATH_W) 'encoding/payloads/ike_header.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ike_header.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_header.Tpo $(DEPDIR)/ike_header.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ike_header.c' object='ike_header.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_header.obj `if test -f 'encoding/payloads/ike_header.c'; then $(CYGPATH_W) 'encoding/payloads/ike_header.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ike_header.c'; fi`
-
-ke_payload.o: encoding/payloads/ke_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ke_payload.o -MD -MP -MF $(DEPDIR)/ke_payload.Tpo -c -o ke_payload.o `test -f 'encoding/payloads/ke_payload.c' || echo '$(srcdir)/'`encoding/payloads/ke_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ke_payload.Tpo $(DEPDIR)/ke_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ke_payload.c' object='ke_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ke_payload.o `test -f 'encoding/payloads/ke_payload.c' || echo '$(srcdir)/'`encoding/payloads/ke_payload.c
-
-ke_payload.obj: encoding/payloads/ke_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ke_payload.obj -MD -MP -MF $(DEPDIR)/ke_payload.Tpo -c -o ke_payload.obj `if test -f 'encoding/payloads/ke_payload.c'; then $(CYGPATH_W) 'encoding/payloads/ke_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ke_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ke_payload.Tpo $(DEPDIR)/ke_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ke_payload.c' object='ke_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ke_payload.obj `if test -f 'encoding/payloads/ke_payload.c'; then $(CYGPATH_W) 'encoding/payloads/ke_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ke_payload.c'; fi`
-
-nonce_payload.o: encoding/payloads/nonce_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nonce_payload.o -MD -MP -MF $(DEPDIR)/nonce_payload.Tpo -c -o nonce_payload.o `test -f 'encoding/payloads/nonce_payload.c' || echo '$(srcdir)/'`encoding/payloads/nonce_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nonce_payload.Tpo $(DEPDIR)/nonce_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/nonce_payload.c' object='nonce_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nonce_payload.o `test -f 'encoding/payloads/nonce_payload.c' || echo '$(srcdir)/'`encoding/payloads/nonce_payload.c
-
-nonce_payload.obj: encoding/payloads/nonce_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nonce_payload.obj -MD -MP -MF $(DEPDIR)/nonce_payload.Tpo -c -o nonce_payload.obj `if test -f 'encoding/payloads/nonce_payload.c'; then $(CYGPATH_W) 'encoding/payloads/nonce_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/nonce_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nonce_payload.Tpo $(DEPDIR)/nonce_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/nonce_payload.c' object='nonce_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nonce_payload.obj `if test -f 'encoding/payloads/nonce_payload.c'; then $(CYGPATH_W) 'encoding/payloads/nonce_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/nonce_payload.c'; fi`
-
-notify_payload.o: encoding/payloads/notify_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT notify_payload.o -MD -MP -MF $(DEPDIR)/notify_payload.Tpo -c -o notify_payload.o `test -f 'encoding/payloads/notify_payload.c' || echo '$(srcdir)/'`encoding/payloads/notify_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/notify_payload.Tpo $(DEPDIR)/notify_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/notify_payload.c' object='notify_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o notify_payload.o `test -f 'encoding/payloads/notify_payload.c' || echo '$(srcdir)/'`encoding/payloads/notify_payload.c
-
-notify_payload.obj: encoding/payloads/notify_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT notify_payload.obj -MD -MP -MF $(DEPDIR)/notify_payload.Tpo -c -o notify_payload.obj `if test -f 'encoding/payloads/notify_payload.c'; then $(CYGPATH_W) 'encoding/payloads/notify_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/notify_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/notify_payload.Tpo $(DEPDIR)/notify_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/notify_payload.c' object='notify_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o notify_payload.obj `if test -f 'encoding/payloads/notify_payload.c'; then $(CYGPATH_W) 'encoding/payloads/notify_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/notify_payload.c'; fi`
-
-payload.o: encoding/payloads/payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT payload.o -MD -MP -MF $(DEPDIR)/payload.Tpo -c -o payload.o `test -f 'encoding/payloads/payload.c' || echo '$(srcdir)/'`encoding/payloads/payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/payload.Tpo $(DEPDIR)/payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/payload.c' object='payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o payload.o `test -f 'encoding/payloads/payload.c' || echo '$(srcdir)/'`encoding/payloads/payload.c
-
-payload.obj: encoding/payloads/payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT payload.obj -MD -MP -MF $(DEPDIR)/payload.Tpo -c -o payload.obj `if test -f 'encoding/payloads/payload.c'; then $(CYGPATH_W) 'encoding/payloads/payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/payload.Tpo $(DEPDIR)/payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/payload.c' object='payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o payload.obj `if test -f 'encoding/payloads/payload.c'; then $(CYGPATH_W) 'encoding/payloads/payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/payload.c'; fi`
-
-proposal_substructure.o: encoding/payloads/proposal_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal_substructure.o -MD -MP -MF $(DEPDIR)/proposal_substructure.Tpo -c -o proposal_substructure.o `test -f 'encoding/payloads/proposal_substructure.c' || echo '$(srcdir)/'`encoding/payloads/proposal_substructure.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal_substructure.Tpo $(DEPDIR)/proposal_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/proposal_substructure.c' object='proposal_substructure.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal_substructure.o `test -f 'encoding/payloads/proposal_substructure.c' || echo '$(srcdir)/'`encoding/payloads/proposal_substructure.c
-
-proposal_substructure.obj: encoding/payloads/proposal_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal_substructure.obj -MD -MP -MF $(DEPDIR)/proposal_substructure.Tpo -c -o proposal_substructure.obj `if test -f 'encoding/payloads/proposal_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/proposal_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/proposal_substructure.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal_substructure.Tpo $(DEPDIR)/proposal_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/proposal_substructure.c' object='proposal_substructure.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal_substructure.obj `if test -f 'encoding/payloads/proposal_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/proposal_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/proposal_substructure.c'; fi`
-
-sa_payload.o: encoding/payloads/sa_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sa_payload.o -MD -MP -MF $(DEPDIR)/sa_payload.Tpo -c -o sa_payload.o `test -f 'encoding/payloads/sa_payload.c' || echo '$(srcdir)/'`encoding/payloads/sa_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sa_payload.Tpo $(DEPDIR)/sa_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/sa_payload.c' object='sa_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sa_payload.o `test -f 'encoding/payloads/sa_payload.c' || echo '$(srcdir)/'`encoding/payloads/sa_payload.c
-
-sa_payload.obj: encoding/payloads/sa_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sa_payload.obj -MD -MP -MF $(DEPDIR)/sa_payload.Tpo -c -o sa_payload.obj `if test -f 'encoding/payloads/sa_payload.c'; then $(CYGPATH_W) 'encoding/payloads/sa_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/sa_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sa_payload.Tpo $(DEPDIR)/sa_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/sa_payload.c' object='sa_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sa_payload.obj `if test -f 'encoding/payloads/sa_payload.c'; then $(CYGPATH_W) 'encoding/payloads/sa_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/sa_payload.c'; fi`
-
-traffic_selector_substructure.o: encoding/payloads/traffic_selector_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT traffic_selector_substructure.o -MD -MP -MF $(DEPDIR)/traffic_selector_substructure.Tpo -c -o traffic_selector_substructure.o `test -f 'encoding/payloads/traffic_selector_substructure.c' || echo '$(srcdir)/'`encoding/payloads/traffic_selector_substructure.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/traffic_selector_substructure.Tpo $(DEPDIR)/traffic_selector_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/traffic_selector_substructure.c' object='traffic_selector_substructure.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o traffic_selector_substructure.o `test -f 'encoding/payloads/traffic_selector_substructure.c' || echo '$(srcdir)/'`encoding/payloads/traffic_selector_substructure.c
-
-traffic_selector_substructure.obj: encoding/payloads/traffic_selector_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT traffic_selector_substructure.obj -MD -MP -MF $(DEPDIR)/traffic_selector_substructure.Tpo -c -o traffic_selector_substructure.obj `if test -f 'encoding/payloads/traffic_selector_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/traffic_selector_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/traffic_selector_substructure.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/traffic_selector_substructure.Tpo $(DEPDIR)/traffic_selector_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/traffic_selector_substructure.c' object='traffic_selector_substructure.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o traffic_selector_substructure.obj `if test -f 'encoding/payloads/traffic_selector_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/traffic_selector_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/traffic_selector_substructure.c'; fi`
-
-transform_attribute.o: encoding/payloads/transform_attribute.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_attribute.o -MD -MP -MF $(DEPDIR)/transform_attribute.Tpo -c -o transform_attribute.o `test -f 'encoding/payloads/transform_attribute.c' || echo '$(srcdir)/'`encoding/payloads/transform_attribute.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_attribute.Tpo $(DEPDIR)/transform_attribute.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_attribute.c' object='transform_attribute.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_attribute.o `test -f 'encoding/payloads/transform_attribute.c' || echo '$(srcdir)/'`encoding/payloads/transform_attribute.c
-
-transform_attribute.obj: encoding/payloads/transform_attribute.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_attribute.obj -MD -MP -MF $(DEPDIR)/transform_attribute.Tpo -c -o transform_attribute.obj `if test -f 'encoding/payloads/transform_attribute.c'; then $(CYGPATH_W) 'encoding/payloads/transform_attribute.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/transform_attribute.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_attribute.Tpo $(DEPDIR)/transform_attribute.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_attribute.c' object='transform_attribute.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_attribute.obj `if test -f 'encoding/payloads/transform_attribute.c'; then $(CYGPATH_W) 'encoding/payloads/transform_attribute.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/transform_attribute.c'; fi`
-
-transform_substructure.o: encoding/payloads/transform_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_substructure.o -MD -MP -MF $(DEPDIR)/transform_substructure.Tpo -c -o transform_substructure.o `test -f 'encoding/payloads/transform_substructure.c' || echo '$(srcdir)/'`encoding/payloads/transform_substructure.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_substructure.Tpo $(DEPDIR)/transform_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_substructure.c' object='transform_substructure.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_substructure.o `test -f 'encoding/payloads/transform_substructure.c' || echo '$(srcdir)/'`encoding/payloads/transform_substructure.c
-
-transform_substructure.obj: encoding/payloads/transform_substructure.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_substructure.obj -MD -MP -MF $(DEPDIR)/transform_substructure.Tpo -c -o transform_substructure.obj `if test -f 'encoding/payloads/transform_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/transform_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/transform_substructure.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_substructure.Tpo $(DEPDIR)/transform_substructure.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_substructure.c' object='transform_substructure.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_substructure.obj `if test -f 'encoding/payloads/transform_substructure.c'; then $(CYGPATH_W) 'encoding/payloads/transform_substructure.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/transform_substructure.c'; fi`
-
-ts_payload.o: encoding/payloads/ts_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ts_payload.o -MD -MP -MF $(DEPDIR)/ts_payload.Tpo -c -o ts_payload.o `test -f 'encoding/payloads/ts_payload.c' || echo '$(srcdir)/'`encoding/payloads/ts_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ts_payload.Tpo $(DEPDIR)/ts_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ts_payload.c' object='ts_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ts_payload.o `test -f 'encoding/payloads/ts_payload.c' || echo '$(srcdir)/'`encoding/payloads/ts_payload.c
-
-ts_payload.obj: encoding/payloads/ts_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ts_payload.obj -MD -MP -MF $(DEPDIR)/ts_payload.Tpo -c -o ts_payload.obj `if test -f 'encoding/payloads/ts_payload.c'; then $(CYGPATH_W) 'encoding/payloads/ts_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ts_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ts_payload.Tpo $(DEPDIR)/ts_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ts_payload.c' object='ts_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ts_payload.obj `if test -f 'encoding/payloads/ts_payload.c'; then $(CYGPATH_W) 'encoding/payloads/ts_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/ts_payload.c'; fi`
-
-unknown_payload.o: encoding/payloads/unknown_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unknown_payload.o -MD -MP -MF $(DEPDIR)/unknown_payload.Tpo -c -o unknown_payload.o `test -f 'encoding/payloads/unknown_payload.c' || echo '$(srcdir)/'`encoding/payloads/unknown_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unknown_payload.Tpo $(DEPDIR)/unknown_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/unknown_payload.c' object='unknown_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unknown_payload.o `test -f 'encoding/payloads/unknown_payload.c' || echo '$(srcdir)/'`encoding/payloads/unknown_payload.c
-
-unknown_payload.obj: encoding/payloads/unknown_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unknown_payload.obj -MD -MP -MF $(DEPDIR)/unknown_payload.Tpo -c -o unknown_payload.obj `if test -f 'encoding/payloads/unknown_payload.c'; then $(CYGPATH_W) 'encoding/payloads/unknown_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/unknown_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unknown_payload.Tpo $(DEPDIR)/unknown_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/unknown_payload.c' object='unknown_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unknown_payload.obj `if test -f 'encoding/payloads/unknown_payload.c'; then $(CYGPATH_W) 'encoding/payloads/unknown_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/unknown_payload.c'; fi`
-
-vendor_id_payload.o: encoding/payloads/vendor_id_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vendor_id_payload.o -MD -MP -MF $(DEPDIR)/vendor_id_payload.Tpo -c -o vendor_id_payload.o `test -f 'encoding/payloads/vendor_id_payload.c' || echo '$(srcdir)/'`encoding/payloads/vendor_id_payload.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/vendor_id_payload.Tpo $(DEPDIR)/vendor_id_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/vendor_id_payload.c' object='vendor_id_payload.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vendor_id_payload.o `test -f 'encoding/payloads/vendor_id_payload.c' || echo '$(srcdir)/'`encoding/payloads/vendor_id_payload.c
-
-vendor_id_payload.obj: encoding/payloads/vendor_id_payload.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vendor_id_payload.obj -MD -MP -MF $(DEPDIR)/vendor_id_payload.Tpo -c -o vendor_id_payload.obj `if test -f 'encoding/payloads/vendor_id_payload.c'; then $(CYGPATH_W) 'encoding/payloads/vendor_id_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/vendor_id_payload.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/vendor_id_payload.Tpo $(DEPDIR)/vendor_id_payload.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/vendor_id_payload.c' object='vendor_id_payload.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vendor_id_payload.obj `if test -f 'encoding/payloads/vendor_id_payload.c'; then $(CYGPATH_W) 'encoding/payloads/vendor_id_payload.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/vendor_id_payload.c'; fi`
-
-kernel_interface.o: kernel/kernel_interface.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_interface.o -MD -MP -MF $(DEPDIR)/kernel_interface.Tpo -c -o kernel_interface.o `test -f 'kernel/kernel_interface.c' || echo '$(srcdir)/'`kernel/kernel_interface.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_interface.Tpo $(DEPDIR)/kernel_interface.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_interface.c' object='kernel_interface.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_interface.o `test -f 'kernel/kernel_interface.c' || echo '$(srcdir)/'`kernel/kernel_interface.c
-
-kernel_interface.obj: kernel/kernel_interface.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_interface.obj -MD -MP -MF $(DEPDIR)/kernel_interface.Tpo -c -o kernel_interface.obj `if test -f 'kernel/kernel_interface.c'; then $(CYGPATH_W) 'kernel/kernel_interface.c'; else $(CYGPATH_W) '$(srcdir)/kernel/kernel_interface.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_interface.Tpo $(DEPDIR)/kernel_interface.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_interface.c' object='kernel_interface.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_interface.obj `if test -f 'kernel/kernel_interface.c'; then $(CYGPATH_W) 'kernel/kernel_interface.c'; else $(CYGPATH_W) '$(srcdir)/kernel/kernel_interface.c'; fi`
-
-kernel_ipsec.o: kernel/kernel_ipsec.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_ipsec.o -MD -MP -MF $(DEPDIR)/kernel_ipsec.Tpo -c -o kernel_ipsec.o `test -f 'kernel/kernel_ipsec.c' || echo '$(srcdir)/'`kernel/kernel_ipsec.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_ipsec.Tpo $(DEPDIR)/kernel_ipsec.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_ipsec.c' object='kernel_ipsec.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_ipsec.o `test -f 'kernel/kernel_ipsec.c' || echo '$(srcdir)/'`kernel/kernel_ipsec.c
-
-kernel_ipsec.obj: kernel/kernel_ipsec.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_ipsec.obj -MD -MP -MF $(DEPDIR)/kernel_ipsec.Tpo -c -o kernel_ipsec.obj `if test -f 'kernel/kernel_ipsec.c'; then $(CYGPATH_W) 'kernel/kernel_ipsec.c'; else $(CYGPATH_W) '$(srcdir)/kernel/kernel_ipsec.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_ipsec.Tpo $(DEPDIR)/kernel_ipsec.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_ipsec.c' object='kernel_ipsec.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_ipsec.obj `if test -f 'kernel/kernel_ipsec.c'; then $(CYGPATH_W) 'kernel/kernel_ipsec.c'; else $(CYGPATH_W) '$(srcdir)/kernel/kernel_ipsec.c'; fi`
-
-packet.o: network/packet.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.o -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.o `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/packet.c' object='packet.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.o `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
-
-packet.obj: network/packet.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.obj -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.obj `if test -f 'network/packet.c'; then $(CYGPATH_W) 'network/packet.c'; else $(CYGPATH_W) '$(srcdir)/network/packet.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/packet.c' object='packet.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.obj `if test -f 'network/packet.c'; then $(CYGPATH_W) 'network/packet.c'; else $(CYGPATH_W) '$(srcdir)/network/packet.c'; fi`
-
-receiver.o: network/receiver.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT receiver.o -MD -MP -MF $(DEPDIR)/receiver.Tpo -c -o receiver.o `test -f 'network/receiver.c' || echo '$(srcdir)/'`network/receiver.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/receiver.Tpo $(DEPDIR)/receiver.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/receiver.c' object='receiver.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o receiver.o `test -f 'network/receiver.c' || echo '$(srcdir)/'`network/receiver.c
-
-receiver.obj: network/receiver.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT receiver.obj -MD -MP -MF $(DEPDIR)/receiver.Tpo -c -o receiver.obj `if test -f 'network/receiver.c'; then $(CYGPATH_W) 'network/receiver.c'; else $(CYGPATH_W) '$(srcdir)/network/receiver.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/receiver.Tpo $(DEPDIR)/receiver.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/receiver.c' object='receiver.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o receiver.obj `if test -f 'network/receiver.c'; then $(CYGPATH_W) 'network/receiver.c'; else $(CYGPATH_W) '$(srcdir)/network/receiver.c'; fi`
-
-sender.o: network/sender.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sender.o -MD -MP -MF $(DEPDIR)/sender.Tpo -c -o sender.o `test -f 'network/sender.c' || echo '$(srcdir)/'`network/sender.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sender.Tpo $(DEPDIR)/sender.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/sender.c' object='sender.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sender.o `test -f 'network/sender.c' || echo '$(srcdir)/'`network/sender.c
-
-sender.obj: network/sender.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sender.obj -MD -MP -MF $(DEPDIR)/sender.Tpo -c -o sender.obj `if test -f 'network/sender.c'; then $(CYGPATH_W) 'network/sender.c'; else $(CYGPATH_W) '$(srcdir)/network/sender.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sender.Tpo $(DEPDIR)/sender.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/sender.c' object='sender.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sender.obj `if test -f 'network/sender.c'; then $(CYGPATH_W) 'network/sender.c'; else $(CYGPATH_W) '$(srcdir)/network/sender.c'; fi`
-
-acquire_job.o: processing/jobs/acquire_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acquire_job.o -MD -MP -MF $(DEPDIR)/acquire_job.Tpo -c -o acquire_job.o `test -f 'processing/jobs/acquire_job.c' || echo '$(srcdir)/'`processing/jobs/acquire_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acquire_job.Tpo $(DEPDIR)/acquire_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/acquire_job.c' object='acquire_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acquire_job.o `test -f 'processing/jobs/acquire_job.c' || echo '$(srcdir)/'`processing/jobs/acquire_job.c
-
-acquire_job.obj: processing/jobs/acquire_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acquire_job.obj -MD -MP -MF $(DEPDIR)/acquire_job.Tpo -c -o acquire_job.obj `if test -f 'processing/jobs/acquire_job.c'; then $(CYGPATH_W) 'processing/jobs/acquire_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/acquire_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acquire_job.Tpo $(DEPDIR)/acquire_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/acquire_job.c' object='acquire_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acquire_job.obj `if test -f 'processing/jobs/acquire_job.c'; then $(CYGPATH_W) 'processing/jobs/acquire_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/acquire_job.c'; fi`
-
-callback_job.o: processing/jobs/callback_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT callback_job.o -MD -MP -MF $(DEPDIR)/callback_job.Tpo -c -o callback_job.o `test -f 'processing/jobs/callback_job.c' || echo '$(srcdir)/'`processing/jobs/callback_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/callback_job.Tpo $(DEPDIR)/callback_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/callback_job.c' object='callback_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o callback_job.o `test -f 'processing/jobs/callback_job.c' || echo '$(srcdir)/'`processing/jobs/callback_job.c
-
-callback_job.obj: processing/jobs/callback_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT callback_job.obj -MD -MP -MF $(DEPDIR)/callback_job.Tpo -c -o callback_job.obj `if test -f 'processing/jobs/callback_job.c'; then $(CYGPATH_W) 'processing/jobs/callback_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/callback_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/callback_job.Tpo $(DEPDIR)/callback_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/callback_job.c' object='callback_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o callback_job.obj `if test -f 'processing/jobs/callback_job.c'; then $(CYGPATH_W) 'processing/jobs/callback_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/callback_job.c'; fi`
-
-delete_child_sa_job.o: processing/jobs/delete_child_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_child_sa_job.o -MD -MP -MF $(DEPDIR)/delete_child_sa_job.Tpo -c -o delete_child_sa_job.o `test -f 'processing/jobs/delete_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_child_sa_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_child_sa_job.Tpo $(DEPDIR)/delete_child_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_child_sa_job.c' object='delete_child_sa_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_child_sa_job.o `test -f 'processing/jobs/delete_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_child_sa_job.c
-
-delete_child_sa_job.obj: processing/jobs/delete_child_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_child_sa_job.obj -MD -MP -MF $(DEPDIR)/delete_child_sa_job.Tpo -c -o delete_child_sa_job.obj `if test -f 'processing/jobs/delete_child_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/delete_child_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/delete_child_sa_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_child_sa_job.Tpo $(DEPDIR)/delete_child_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_child_sa_job.c' object='delete_child_sa_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_child_sa_job.obj `if test -f 'processing/jobs/delete_child_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/delete_child_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/delete_child_sa_job.c'; fi`
-
-delete_ike_sa_job.o: processing/jobs/delete_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_ike_sa_job.o -MD -MP -MF $(DEPDIR)/delete_ike_sa_job.Tpo -c -o delete_ike_sa_job.o `test -f 'processing/jobs/delete_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_ike_sa_job.Tpo $(DEPDIR)/delete_ike_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_ike_sa_job.c' object='delete_ike_sa_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_ike_sa_job.o `test -f 'processing/jobs/delete_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_ike_sa_job.c
-
-delete_ike_sa_job.obj: processing/jobs/delete_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_ike_sa_job.obj -MD -MP -MF $(DEPDIR)/delete_ike_sa_job.Tpo -c -o delete_ike_sa_job.obj `if test -f 'processing/jobs/delete_ike_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/delete_ike_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/delete_ike_sa_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_ike_sa_job.Tpo $(DEPDIR)/delete_ike_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_ike_sa_job.c' object='delete_ike_sa_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_ike_sa_job.obj `if test -f 'processing/jobs/delete_ike_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/delete_ike_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/delete_ike_sa_job.c'; fi`
-
-migrate_job.o: processing/jobs/migrate_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT migrate_job.o -MD -MP -MF $(DEPDIR)/migrate_job.Tpo -c -o migrate_job.o `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/migrate_job.Tpo $(DEPDIR)/migrate_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/migrate_job.c' object='migrate_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o migrate_job.o `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
-
-migrate_job.obj: processing/jobs/migrate_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT migrate_job.obj -MD -MP -MF $(DEPDIR)/migrate_job.Tpo -c -o migrate_job.obj `if test -f 'processing/jobs/migrate_job.c'; then $(CYGPATH_W) 'processing/jobs/migrate_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/migrate_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/migrate_job.Tpo $(DEPDIR)/migrate_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/migrate_job.c' object='migrate_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o migrate_job.obj `if test -f 'processing/jobs/migrate_job.c'; then $(CYGPATH_W) 'processing/jobs/migrate_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/migrate_job.c'; fi`
-
-process_message_job.o: processing/jobs/process_message_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_message_job.o -MD -MP -MF $(DEPDIR)/process_message_job.Tpo -c -o process_message_job.o `test -f 'processing/jobs/process_message_job.c' || echo '$(srcdir)/'`processing/jobs/process_message_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/process_message_job.Tpo $(DEPDIR)/process_message_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/process_message_job.c' object='process_message_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_message_job.o `test -f 'processing/jobs/process_message_job.c' || echo '$(srcdir)/'`processing/jobs/process_message_job.c
-
-process_message_job.obj: processing/jobs/process_message_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_message_job.obj -MD -MP -MF $(DEPDIR)/process_message_job.Tpo -c -o process_message_job.obj `if test -f 'processing/jobs/process_message_job.c'; then $(CYGPATH_W) 'processing/jobs/process_message_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/process_message_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/process_message_job.Tpo $(DEPDIR)/process_message_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/process_message_job.c' object='process_message_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_message_job.obj `if test -f 'processing/jobs/process_message_job.c'; then $(CYGPATH_W) 'processing/jobs/process_message_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/process_message_job.c'; fi`
-
-rekey_child_sa_job.o: processing/jobs/rekey_child_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_child_sa_job.o -MD -MP -MF $(DEPDIR)/rekey_child_sa_job.Tpo -c -o rekey_child_sa_job.o `test -f 'processing/jobs/rekey_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_child_sa_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_child_sa_job.Tpo $(DEPDIR)/rekey_child_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_child_sa_job.c' object='rekey_child_sa_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_child_sa_job.o `test -f 'processing/jobs/rekey_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_child_sa_job.c
-
-rekey_child_sa_job.obj: processing/jobs/rekey_child_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_child_sa_job.obj -MD -MP -MF $(DEPDIR)/rekey_child_sa_job.Tpo -c -o rekey_child_sa_job.obj `if test -f 'processing/jobs/rekey_child_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/rekey_child_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/rekey_child_sa_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_child_sa_job.Tpo $(DEPDIR)/rekey_child_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_child_sa_job.c' object='rekey_child_sa_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_child_sa_job.obj `if test -f 'processing/jobs/rekey_child_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/rekey_child_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/rekey_child_sa_job.c'; fi`
-
-rekey_ike_sa_job.o: processing/jobs/rekey_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_ike_sa_job.o -MD -MP -MF $(DEPDIR)/rekey_ike_sa_job.Tpo -c -o rekey_ike_sa_job.o `test -f 'processing/jobs/rekey_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_ike_sa_job.Tpo $(DEPDIR)/rekey_ike_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_ike_sa_job.c' object='rekey_ike_sa_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_ike_sa_job.o `test -f 'processing/jobs/rekey_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_ike_sa_job.c
-
-rekey_ike_sa_job.obj: processing/jobs/rekey_ike_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_ike_sa_job.obj -MD -MP -MF $(DEPDIR)/rekey_ike_sa_job.Tpo -c -o rekey_ike_sa_job.obj `if test -f 'processing/jobs/rekey_ike_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/rekey_ike_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/rekey_ike_sa_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_ike_sa_job.Tpo $(DEPDIR)/rekey_ike_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_ike_sa_job.c' object='rekey_ike_sa_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_ike_sa_job.obj `if test -f 'processing/jobs/rekey_ike_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/rekey_ike_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/rekey_ike_sa_job.c'; fi`
-
-retransmit_job.o: processing/jobs/retransmit_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retransmit_job.o -MD -MP -MF $(DEPDIR)/retransmit_job.Tpo -c -o retransmit_job.o `test -f 'processing/jobs/retransmit_job.c' || echo '$(srcdir)/'`processing/jobs/retransmit_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/retransmit_job.Tpo $(DEPDIR)/retransmit_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/retransmit_job.c' object='retransmit_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retransmit_job.o `test -f 'processing/jobs/retransmit_job.c' || echo '$(srcdir)/'`processing/jobs/retransmit_job.c
-
-retransmit_job.obj: processing/jobs/retransmit_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retransmit_job.obj -MD -MP -MF $(DEPDIR)/retransmit_job.Tpo -c -o retransmit_job.obj `if test -f 'processing/jobs/retransmit_job.c'; then $(CYGPATH_W) 'processing/jobs/retransmit_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/retransmit_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/retransmit_job.Tpo $(DEPDIR)/retransmit_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/retransmit_job.c' object='retransmit_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retransmit_job.obj `if test -f 'processing/jobs/retransmit_job.c'; then $(CYGPATH_W) 'processing/jobs/retransmit_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/retransmit_job.c'; fi`
-
-send_dpd_job.o: processing/jobs/send_dpd_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_dpd_job.o -MD -MP -MF $(DEPDIR)/send_dpd_job.Tpo -c -o send_dpd_job.o `test -f 'processing/jobs/send_dpd_job.c' || echo '$(srcdir)/'`processing/jobs/send_dpd_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_dpd_job.Tpo $(DEPDIR)/send_dpd_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_dpd_job.c' object='send_dpd_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_dpd_job.o `test -f 'processing/jobs/send_dpd_job.c' || echo '$(srcdir)/'`processing/jobs/send_dpd_job.c
-
-send_dpd_job.obj: processing/jobs/send_dpd_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_dpd_job.obj -MD -MP -MF $(DEPDIR)/send_dpd_job.Tpo -c -o send_dpd_job.obj `if test -f 'processing/jobs/send_dpd_job.c'; then $(CYGPATH_W) 'processing/jobs/send_dpd_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/send_dpd_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_dpd_job.Tpo $(DEPDIR)/send_dpd_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_dpd_job.c' object='send_dpd_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_dpd_job.obj `if test -f 'processing/jobs/send_dpd_job.c'; then $(CYGPATH_W) 'processing/jobs/send_dpd_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/send_dpd_job.c'; fi`
-
-send_keepalive_job.o: processing/jobs/send_keepalive_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_keepalive_job.o -MD -MP -MF $(DEPDIR)/send_keepalive_job.Tpo -c -o send_keepalive_job.o `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_keepalive_job.Tpo $(DEPDIR)/send_keepalive_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_keepalive_job.c' object='send_keepalive_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_keepalive_job.o `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c
-
-send_keepalive_job.obj: processing/jobs/send_keepalive_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_keepalive_job.obj -MD -MP -MF $(DEPDIR)/send_keepalive_job.Tpo -c -o send_keepalive_job.obj `if test -f 'processing/jobs/send_keepalive_job.c'; then $(CYGPATH_W) 'processing/jobs/send_keepalive_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/send_keepalive_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_keepalive_job.Tpo $(DEPDIR)/send_keepalive_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_keepalive_job.c' object='send_keepalive_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_keepalive_job.obj `if test -f 'processing/jobs/send_keepalive_job.c'; then $(CYGPATH_W) 'processing/jobs/send_keepalive_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/send_keepalive_job.c'; fi`
-
-roam_job.o: processing/jobs/roam_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT roam_job.o -MD -MP -MF $(DEPDIR)/roam_job.Tpo -c -o roam_job.o `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/roam_job.Tpo $(DEPDIR)/roam_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/roam_job.c' object='roam_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o roam_job.o `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c
-
-roam_job.obj: processing/jobs/roam_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT roam_job.obj -MD -MP -MF $(DEPDIR)/roam_job.Tpo -c -o roam_job.obj `if test -f 'processing/jobs/roam_job.c'; then $(CYGPATH_W) 'processing/jobs/roam_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/roam_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/roam_job.Tpo $(DEPDIR)/roam_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/roam_job.c' object='roam_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o roam_job.obj `if test -f 'processing/jobs/roam_job.c'; then $(CYGPATH_W) 'processing/jobs/roam_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/roam_job.c'; fi`
-
-update_sa_job.o: processing/jobs/update_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT update_sa_job.o -MD -MP -MF $(DEPDIR)/update_sa_job.Tpo -c -o update_sa_job.o `test -f 'processing/jobs/update_sa_job.c' || echo '$(srcdir)/'`processing/jobs/update_sa_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/update_sa_job.Tpo $(DEPDIR)/update_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/update_sa_job.c' object='update_sa_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o update_sa_job.o `test -f 'processing/jobs/update_sa_job.c' || echo '$(srcdir)/'`processing/jobs/update_sa_job.c
-
-update_sa_job.obj: processing/jobs/update_sa_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT update_sa_job.obj -MD -MP -MF $(DEPDIR)/update_sa_job.Tpo -c -o update_sa_job.obj `if test -f 'processing/jobs/update_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/update_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/update_sa_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/update_sa_job.Tpo $(DEPDIR)/update_sa_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/update_sa_job.c' object='update_sa_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o update_sa_job.obj `if test -f 'processing/jobs/update_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/update_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/update_sa_job.c'; fi`
-
-inactivity_job.o: processing/jobs/inactivity_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inactivity_job.o -MD -MP -MF $(DEPDIR)/inactivity_job.Tpo -c -o inactivity_job.o `test -f 'processing/jobs/inactivity_job.c' || echo '$(srcdir)/'`processing/jobs/inactivity_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/inactivity_job.Tpo $(DEPDIR)/inactivity_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/inactivity_job.c' object='inactivity_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inactivity_job.o `test -f 'processing/jobs/inactivity_job.c' || echo '$(srcdir)/'`processing/jobs/inactivity_job.c
-
-inactivity_job.obj: processing/jobs/inactivity_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inactivity_job.obj -MD -MP -MF $(DEPDIR)/inactivity_job.Tpo -c -o inactivity_job.obj `if test -f 'processing/jobs/inactivity_job.c'; then $(CYGPATH_W) 'processing/jobs/inactivity_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/inactivity_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/inactivity_job.Tpo $(DEPDIR)/inactivity_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/inactivity_job.c' object='inactivity_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inactivity_job.obj `if test -f 'processing/jobs/inactivity_job.c'; then $(CYGPATH_W) 'processing/jobs/inactivity_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/inactivity_job.c'; fi`
-
-scheduler.o: processing/scheduler.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT scheduler.o -MD -MP -MF $(DEPDIR)/scheduler.Tpo -c -o scheduler.o `test -f 'processing/scheduler.c' || echo '$(srcdir)/'`processing/scheduler.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/scheduler.Tpo $(DEPDIR)/scheduler.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/scheduler.c' object='scheduler.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o scheduler.o `test -f 'processing/scheduler.c' || echo '$(srcdir)/'`processing/scheduler.c
-
-scheduler.obj: processing/scheduler.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT scheduler.obj -MD -MP -MF $(DEPDIR)/scheduler.Tpo -c -o scheduler.obj `if test -f 'processing/scheduler.c'; then $(CYGPATH_W) 'processing/scheduler.c'; else $(CYGPATH_W) '$(srcdir)/processing/scheduler.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/scheduler.Tpo $(DEPDIR)/scheduler.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/scheduler.c' object='scheduler.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o scheduler.obj `if test -f 'processing/scheduler.c'; then $(CYGPATH_W) 'processing/scheduler.c'; else $(CYGPATH_W) '$(srcdir)/processing/scheduler.c'; fi`
-
-processor.o: processing/processor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT processor.o -MD -MP -MF $(DEPDIR)/processor.Tpo -c -o processor.o `test -f 'processing/processor.c' || echo '$(srcdir)/'`processing/processor.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/processor.Tpo $(DEPDIR)/processor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/processor.c' object='processor.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o processor.o `test -f 'processing/processor.c' || echo '$(srcdir)/'`processing/processor.c
-
-processor.obj: processing/processor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT processor.obj -MD -MP -MF $(DEPDIR)/processor.Tpo -c -o processor.obj `if test -f 'processing/processor.c'; then $(CYGPATH_W) 'processing/processor.c'; else $(CYGPATH_W) '$(srcdir)/processing/processor.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/processor.Tpo $(DEPDIR)/processor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/processor.c' object='processor.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o processor.obj `if test -f 'processing/processor.c'; then $(CYGPATH_W) 'processing/processor.c'; else $(CYGPATH_W) '$(srcdir)/processing/processor.c'; fi`
-
-authenticator.o: sa/authenticators/authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT authenticator.o -MD -MP -MF $(DEPDIR)/authenticator.Tpo -c -o authenticator.o `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/authenticator.Tpo $(DEPDIR)/authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/authenticator.c' object='authenticator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o authenticator.o `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
-
-authenticator.obj: sa/authenticators/authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT authenticator.obj -MD -MP -MF $(DEPDIR)/authenticator.Tpo -c -o authenticator.obj `if test -f 'sa/authenticators/authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/authenticator.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/authenticator.Tpo $(DEPDIR)/authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/authenticator.c' object='authenticator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o authenticator.obj `if test -f 'sa/authenticators/authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/authenticator.c'; fi`
-
-eap_authenticator.o: sa/authenticators/eap_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_authenticator.o -MD -MP -MF $(DEPDIR)/eap_authenticator.Tpo -c -o eap_authenticator.o `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_authenticator.Tpo $(DEPDIR)/eap_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap_authenticator.c' object='eap_authenticator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_authenticator.o `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
-
-eap_authenticator.obj: sa/authenticators/eap_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_authenticator.obj -MD -MP -MF $(DEPDIR)/eap_authenticator.Tpo -c -o eap_authenticator.obj `if test -f 'sa/authenticators/eap_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/eap_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap_authenticator.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_authenticator.Tpo $(DEPDIR)/eap_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap_authenticator.c' object='eap_authenticator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_authenticator.obj `if test -f 'sa/authenticators/eap_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/eap_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap_authenticator.c'; fi`
-
-eap_method.o: sa/authenticators/eap/eap_method.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_method.o -MD -MP -MF $(DEPDIR)/eap_method.Tpo -c -o eap_method.o `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_method.Tpo $(DEPDIR)/eap_method.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_method.c' object='eap_method.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.o `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
-
-eap_method.obj: sa/authenticators/eap/eap_method.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_method.obj -MD -MP -MF $(DEPDIR)/eap_method.Tpo -c -o eap_method.obj `if test -f 'sa/authenticators/eap/eap_method.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_method.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_method.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_method.Tpo $(DEPDIR)/eap_method.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_method.c' object='eap_method.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.obj `if test -f 'sa/authenticators/eap/eap_method.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_method.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_method.c'; fi`
-
-eap_manager.o: sa/authenticators/eap/eap_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.o -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.o `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.o `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
-
-eap_manager.obj: sa/authenticators/eap/eap_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.obj -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.obj `if test -f 'sa/authenticators/eap/eap_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.obj `if test -f 'sa/authenticators/eap/eap_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_manager.c'; fi`
-
-sim_manager.o: sa/authenticators/eap/sim_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sim_manager.o -MD -MP -MF $(DEPDIR)/sim_manager.Tpo -c -o sim_manager.o `test -f 'sa/authenticators/eap/sim_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sim_manager.Tpo $(DEPDIR)/sim_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/sim_manager.c' object='sim_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sim_manager.o `test -f 'sa/authenticators/eap/sim_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim_manager.c
-
-sim_manager.obj: sa/authenticators/eap/sim_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sim_manager.obj -MD -MP -MF $(DEPDIR)/sim_manager.Tpo -c -o sim_manager.obj `if test -f 'sa/authenticators/eap/sim_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/sim_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/sim_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sim_manager.Tpo $(DEPDIR)/sim_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/sim_manager.c' object='sim_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sim_manager.obj `if test -f 'sa/authenticators/eap/sim_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/sim_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/sim_manager.c'; fi`
-
-psk_authenticator.o: sa/authenticators/psk_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.o -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.o `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/psk_authenticator.c' object='psk_authenticator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.o `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
-
-psk_authenticator.obj: sa/authenticators/psk_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.obj -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.obj `if test -f 'sa/authenticators/psk_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/psk_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/psk_authenticator.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/psk_authenticator.c' object='psk_authenticator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.obj `if test -f 'sa/authenticators/psk_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/psk_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/psk_authenticator.c'; fi`
-
-pubkey_authenticator.o: sa/authenticators/pubkey_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.o -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.o `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.o `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
-
-pubkey_authenticator.obj: sa/authenticators/pubkey_authenticator.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.obj -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.obj `if test -f 'sa/authenticators/pubkey_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/pubkey_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/pubkey_authenticator.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.obj `if test -f 'sa/authenticators/pubkey_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/pubkey_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/pubkey_authenticator.c'; fi`
-
-child_sa.o: sa/child_sa.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_sa.o -MD -MP -MF $(DEPDIR)/child_sa.Tpo -c -o child_sa.o `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_sa.Tpo $(DEPDIR)/child_sa.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/child_sa.c' object='child_sa.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_sa.o `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c
-
-child_sa.obj: sa/child_sa.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_sa.obj -MD -MP -MF $(DEPDIR)/child_sa.Tpo -c -o child_sa.obj `if test -f 'sa/child_sa.c'; then $(CYGPATH_W) 'sa/child_sa.c'; else $(CYGPATH_W) '$(srcdir)/sa/child_sa.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_sa.Tpo $(DEPDIR)/child_sa.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/child_sa.c' object='child_sa.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_sa.obj `if test -f 'sa/child_sa.c'; then $(CYGPATH_W) 'sa/child_sa.c'; else $(CYGPATH_W) '$(srcdir)/sa/child_sa.c'; fi`
-
-ike_sa.o: sa/ike_sa.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa.o -MD -MP -MF $(DEPDIR)/ike_sa.Tpo -c -o ike_sa.o `test -f 'sa/ike_sa.c' || echo '$(srcdir)/'`sa/ike_sa.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa.Tpo $(DEPDIR)/ike_sa.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa.c' object='ike_sa.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa.o `test -f 'sa/ike_sa.c' || echo '$(srcdir)/'`sa/ike_sa.c
-
-ike_sa.obj: sa/ike_sa.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa.obj -MD -MP -MF $(DEPDIR)/ike_sa.Tpo -c -o ike_sa.obj `if test -f 'sa/ike_sa.c'; then $(CYGPATH_W) 'sa/ike_sa.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa.Tpo $(DEPDIR)/ike_sa.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa.c' object='ike_sa.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa.obj `if test -f 'sa/ike_sa.c'; then $(CYGPATH_W) 'sa/ike_sa.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa.c'; fi`
-
-ike_sa_id.o: sa/ike_sa_id.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_id.o -MD -MP -MF $(DEPDIR)/ike_sa_id.Tpo -c -o ike_sa_id.o `test -f 'sa/ike_sa_id.c' || echo '$(srcdir)/'`sa/ike_sa_id.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_id.Tpo $(DEPDIR)/ike_sa_id.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_id.c' object='ike_sa_id.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_id.o `test -f 'sa/ike_sa_id.c' || echo '$(srcdir)/'`sa/ike_sa_id.c
-
-ike_sa_id.obj: sa/ike_sa_id.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_id.obj -MD -MP -MF $(DEPDIR)/ike_sa_id.Tpo -c -o ike_sa_id.obj `if test -f 'sa/ike_sa_id.c'; then $(CYGPATH_W) 'sa/ike_sa_id.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa_id.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_id.Tpo $(DEPDIR)/ike_sa_id.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_id.c' object='ike_sa_id.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_id.obj `if test -f 'sa/ike_sa_id.c'; then $(CYGPATH_W) 'sa/ike_sa_id.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa_id.c'; fi`
-
-ike_sa_manager.o: sa/ike_sa_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_manager.o -MD -MP -MF $(DEPDIR)/ike_sa_manager.Tpo -c -o ike_sa_manager.o `test -f 'sa/ike_sa_manager.c' || echo '$(srcdir)/'`sa/ike_sa_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_manager.Tpo $(DEPDIR)/ike_sa_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_manager.c' object='ike_sa_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_manager.o `test -f 'sa/ike_sa_manager.c' || echo '$(srcdir)/'`sa/ike_sa_manager.c
-
-ike_sa_manager.obj: sa/ike_sa_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_manager.obj -MD -MP -MF $(DEPDIR)/ike_sa_manager.Tpo -c -o ike_sa_manager.obj `if test -f 'sa/ike_sa_manager.c'; then $(CYGPATH_W) 'sa/ike_sa_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_manager.Tpo $(DEPDIR)/ike_sa_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_manager.c' object='ike_sa_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_manager.obj `if test -f 'sa/ike_sa_manager.c'; then $(CYGPATH_W) 'sa/ike_sa_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/ike_sa_manager.c'; fi`
-
-task_manager.o: sa/task_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_manager.o -MD -MP -MF $(DEPDIR)/task_manager.Tpo -c -o task_manager.o `test -f 'sa/task_manager.c' || echo '$(srcdir)/'`sa/task_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task_manager.Tpo $(DEPDIR)/task_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/task_manager.c' object='task_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager.o `test -f 'sa/task_manager.c' || echo '$(srcdir)/'`sa/task_manager.c
-
-task_manager.obj: sa/task_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_manager.obj -MD -MP -MF $(DEPDIR)/task_manager.Tpo -c -o task_manager.obj `if test -f 'sa/task_manager.c'; then $(CYGPATH_W) 'sa/task_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/task_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task_manager.Tpo $(DEPDIR)/task_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/task_manager.c' object='task_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager.obj `if test -f 'sa/task_manager.c'; then $(CYGPATH_W) 'sa/task_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/task_manager.c'; fi`
-
-keymat.o: sa/keymat.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.o -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.o `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.o `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
-
-keymat.obj: sa/keymat.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.obj -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.obj `if test -f 'sa/keymat.c'; then $(CYGPATH_W) 'sa/keymat.c'; else $(CYGPATH_W) '$(srcdir)/sa/keymat.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.obj `if test -f 'sa/keymat.c'; then $(CYGPATH_W) 'sa/keymat.c'; else $(CYGPATH_W) '$(srcdir)/sa/keymat.c'; fi`
-
-trap_manager.o: sa/trap_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT trap_manager.o -MD -MP -MF $(DEPDIR)/trap_manager.Tpo -c -o trap_manager.o `test -f 'sa/trap_manager.c' || echo '$(srcdir)/'`sa/trap_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/trap_manager.Tpo $(DEPDIR)/trap_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/trap_manager.c' object='trap_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o trap_manager.o `test -f 'sa/trap_manager.c' || echo '$(srcdir)/'`sa/trap_manager.c
-
-trap_manager.obj: sa/trap_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT trap_manager.obj -MD -MP -MF $(DEPDIR)/trap_manager.Tpo -c -o trap_manager.obj `if test -f 'sa/trap_manager.c'; then $(CYGPATH_W) 'sa/trap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/trap_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/trap_manager.Tpo $(DEPDIR)/trap_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/trap_manager.c' object='trap_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o trap_manager.obj `if test -f 'sa/trap_manager.c'; then $(CYGPATH_W) 'sa/trap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/trap_manager.c'; fi`
-
-child_create.o: sa/tasks/child_create.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.o -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.o `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_create.Tpo $(DEPDIR)/child_create.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_create.c' object='child_create.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_create.o `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
-
-child_create.obj: sa/tasks/child_create.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.obj -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.obj `if test -f 'sa/tasks/child_create.c'; then $(CYGPATH_W) 'sa/tasks/child_create.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_create.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_create.Tpo $(DEPDIR)/child_create.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_create.c' object='child_create.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_create.obj `if test -f 'sa/tasks/child_create.c'; then $(CYGPATH_W) 'sa/tasks/child_create.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_create.c'; fi`
-
-child_delete.o: sa/tasks/child_delete.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_delete.o -MD -MP -MF $(DEPDIR)/child_delete.Tpo -c -o child_delete.o `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_delete.Tpo $(DEPDIR)/child_delete.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_delete.c' object='child_delete.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_delete.o `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
-
-child_delete.obj: sa/tasks/child_delete.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_delete.obj -MD -MP -MF $(DEPDIR)/child_delete.Tpo -c -o child_delete.obj `if test -f 'sa/tasks/child_delete.c'; then $(CYGPATH_W) 'sa/tasks/child_delete.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_delete.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_delete.Tpo $(DEPDIR)/child_delete.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_delete.c' object='child_delete.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_delete.obj `if test -f 'sa/tasks/child_delete.c'; then $(CYGPATH_W) 'sa/tasks/child_delete.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_delete.c'; fi`
-
-child_rekey.o: sa/tasks/child_rekey.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_rekey.o -MD -MP -MF $(DEPDIR)/child_rekey.Tpo -c -o child_rekey.o `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_rekey.Tpo $(DEPDIR)/child_rekey.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_rekey.c' object='child_rekey.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_rekey.o `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
-
-child_rekey.obj: sa/tasks/child_rekey.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_rekey.obj -MD -MP -MF $(DEPDIR)/child_rekey.Tpo -c -o child_rekey.obj `if test -f 'sa/tasks/child_rekey.c'; then $(CYGPATH_W) 'sa/tasks/child_rekey.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_rekey.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_rekey.Tpo $(DEPDIR)/child_rekey.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_rekey.c' object='child_rekey.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_rekey.obj `if test -f 'sa/tasks/child_rekey.c'; then $(CYGPATH_W) 'sa/tasks/child_rekey.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/child_rekey.c'; fi`
-
-ike_auth.o: sa/tasks/ike_auth.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth.o -MD -MP -MF $(DEPDIR)/ike_auth.Tpo -c -o ike_auth.o `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth.Tpo $(DEPDIR)/ike_auth.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth.c' object='ike_auth.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.o `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
-
-ike_auth.obj: sa/tasks/ike_auth.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth.obj -MD -MP -MF $(DEPDIR)/ike_auth.Tpo -c -o ike_auth.obj `if test -f 'sa/tasks/ike_auth.c'; then $(CYGPATH_W) 'sa/tasks/ike_auth.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_auth.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth.Tpo $(DEPDIR)/ike_auth.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth.c' object='ike_auth.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.obj `if test -f 'sa/tasks/ike_auth.c'; then $(CYGPATH_W) 'sa/tasks/ike_auth.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_auth.c'; fi`
-
-ike_cert_pre.o: sa/tasks/ike_cert_pre.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.o -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.o `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.o `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
-
-ike_cert_pre.obj: sa/tasks/ike_cert_pre.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.obj -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.obj `if test -f 'sa/tasks/ike_cert_pre.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_pre.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_pre.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.obj `if test -f 'sa/tasks/ike_cert_pre.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_pre.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_pre.c'; fi`
-
-ike_cert_post.o: sa/tasks/ike_cert_post.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.o -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.o `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.o `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
-
-ike_cert_post.obj: sa/tasks/ike_cert_post.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.obj -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.obj `if test -f 'sa/tasks/ike_cert_post.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_post.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_post.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.obj `if test -f 'sa/tasks/ike_cert_post.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_post.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_post.c'; fi`
-
-ike_config.o: sa/tasks/ike_config.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.o -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.o `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_config.Tpo $(DEPDIR)/ike_config.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_config.c' object='ike_config.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_config.o `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
-
-ike_config.obj: sa/tasks/ike_config.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.obj -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.obj `if test -f 'sa/tasks/ike_config.c'; then $(CYGPATH_W) 'sa/tasks/ike_config.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_config.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_config.Tpo $(DEPDIR)/ike_config.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_config.c' object='ike_config.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_config.obj `if test -f 'sa/tasks/ike_config.c'; then $(CYGPATH_W) 'sa/tasks/ike_config.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_config.c'; fi`
-
-ike_delete.o: sa/tasks/ike_delete.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_delete.o -MD -MP -MF $(DEPDIR)/ike_delete.Tpo -c -o ike_delete.o `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_delete.Tpo $(DEPDIR)/ike_delete.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_delete.c' object='ike_delete.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_delete.o `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
-
-ike_delete.obj: sa/tasks/ike_delete.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_delete.obj -MD -MP -MF $(DEPDIR)/ike_delete.Tpo -c -o ike_delete.obj `if test -f 'sa/tasks/ike_delete.c'; then $(CYGPATH_W) 'sa/tasks/ike_delete.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_delete.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_delete.Tpo $(DEPDIR)/ike_delete.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_delete.c' object='ike_delete.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_delete.obj `if test -f 'sa/tasks/ike_delete.c'; then $(CYGPATH_W) 'sa/tasks/ike_delete.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_delete.c'; fi`
-
-ike_dpd.o: sa/tasks/ike_dpd.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_dpd.o -MD -MP -MF $(DEPDIR)/ike_dpd.Tpo -c -o ike_dpd.o `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_dpd.Tpo $(DEPDIR)/ike_dpd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_dpd.c' object='ike_dpd.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_dpd.o `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
-
-ike_dpd.obj: sa/tasks/ike_dpd.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_dpd.obj -MD -MP -MF $(DEPDIR)/ike_dpd.Tpo -c -o ike_dpd.obj `if test -f 'sa/tasks/ike_dpd.c'; then $(CYGPATH_W) 'sa/tasks/ike_dpd.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_dpd.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_dpd.Tpo $(DEPDIR)/ike_dpd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_dpd.c' object='ike_dpd.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_dpd.obj `if test -f 'sa/tasks/ike_dpd.c'; then $(CYGPATH_W) 'sa/tasks/ike_dpd.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_dpd.c'; fi`
-
-ike_init.o: sa/tasks/ike_init.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_init.o -MD -MP -MF $(DEPDIR)/ike_init.Tpo -c -o ike_init.o `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_init.Tpo $(DEPDIR)/ike_init.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_init.c' object='ike_init.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_init.o `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
-
-ike_init.obj: sa/tasks/ike_init.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_init.obj -MD -MP -MF $(DEPDIR)/ike_init.Tpo -c -o ike_init.obj `if test -f 'sa/tasks/ike_init.c'; then $(CYGPATH_W) 'sa/tasks/ike_init.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_init.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_init.Tpo $(DEPDIR)/ike_init.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_init.c' object='ike_init.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_init.obj `if test -f 'sa/tasks/ike_init.c'; then $(CYGPATH_W) 'sa/tasks/ike_init.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_init.c'; fi`
-
-ike_natd.o: sa/tasks/ike_natd.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_natd.o -MD -MP -MF $(DEPDIR)/ike_natd.Tpo -c -o ike_natd.o `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_natd.Tpo $(DEPDIR)/ike_natd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_natd.c' object='ike_natd.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_natd.o `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
-
-ike_natd.obj: sa/tasks/ike_natd.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_natd.obj -MD -MP -MF $(DEPDIR)/ike_natd.Tpo -c -o ike_natd.obj `if test -f 'sa/tasks/ike_natd.c'; then $(CYGPATH_W) 'sa/tasks/ike_natd.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_natd.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_natd.Tpo $(DEPDIR)/ike_natd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_natd.c' object='ike_natd.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_natd.obj `if test -f 'sa/tasks/ike_natd.c'; then $(CYGPATH_W) 'sa/tasks/ike_natd.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_natd.c'; fi`
-
-ike_mobike.o: sa/tasks/ike_mobike.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_mobike.o -MD -MP -MF $(DEPDIR)/ike_mobike.Tpo -c -o ike_mobike.o `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_mobike.Tpo $(DEPDIR)/ike_mobike.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_mobike.c' object='ike_mobike.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_mobike.o `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
-
-ike_mobike.obj: sa/tasks/ike_mobike.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_mobike.obj -MD -MP -MF $(DEPDIR)/ike_mobike.Tpo -c -o ike_mobike.obj `if test -f 'sa/tasks/ike_mobike.c'; then $(CYGPATH_W) 'sa/tasks/ike_mobike.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_mobike.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_mobike.Tpo $(DEPDIR)/ike_mobike.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_mobike.c' object='ike_mobike.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_mobike.obj `if test -f 'sa/tasks/ike_mobike.c'; then $(CYGPATH_W) 'sa/tasks/ike_mobike.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_mobike.c'; fi`
-
-ike_rekey.o: sa/tasks/ike_rekey.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_rekey.o -MD -MP -MF $(DEPDIR)/ike_rekey.Tpo -c -o ike_rekey.o `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_rekey.Tpo $(DEPDIR)/ike_rekey.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_rekey.c' object='ike_rekey.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_rekey.o `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
-
-ike_rekey.obj: sa/tasks/ike_rekey.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_rekey.obj -MD -MP -MF $(DEPDIR)/ike_rekey.Tpo -c -o ike_rekey.obj `if test -f 'sa/tasks/ike_rekey.c'; then $(CYGPATH_W) 'sa/tasks/ike_rekey.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_rekey.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_rekey.Tpo $(DEPDIR)/ike_rekey.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_rekey.c' object='ike_rekey.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_rekey.obj `if test -f 'sa/tasks/ike_rekey.c'; then $(CYGPATH_W) 'sa/tasks/ike_rekey.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_rekey.c'; fi`
-
-ike_reauth.o: sa/tasks/ike_reauth.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_reauth.o -MD -MP -MF $(DEPDIR)/ike_reauth.Tpo -c -o ike_reauth.o `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_reauth.Tpo $(DEPDIR)/ike_reauth.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_reauth.c' object='ike_reauth.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_reauth.o `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
-
-ike_reauth.obj: sa/tasks/ike_reauth.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_reauth.obj -MD -MP -MF $(DEPDIR)/ike_reauth.Tpo -c -o ike_reauth.obj `if test -f 'sa/tasks/ike_reauth.c'; then $(CYGPATH_W) 'sa/tasks/ike_reauth.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_reauth.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_reauth.Tpo $(DEPDIR)/ike_reauth.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_reauth.c' object='ike_reauth.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_reauth.obj `if test -f 'sa/tasks/ike_reauth.c'; then $(CYGPATH_W) 'sa/tasks/ike_reauth.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_reauth.c'; fi`
-
-ike_auth_lifetime.o: sa/tasks/ike_auth_lifetime.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_lifetime.o -MD -MP -MF $(DEPDIR)/ike_auth_lifetime.Tpo -c -o ike_auth_lifetime.o `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_lifetime.Tpo $(DEPDIR)/ike_auth_lifetime.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth_lifetime.c' object='ike_auth_lifetime.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_lifetime.o `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
-
-ike_auth_lifetime.obj: sa/tasks/ike_auth_lifetime.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_lifetime.obj -MD -MP -MF $(DEPDIR)/ike_auth_lifetime.Tpo -c -o ike_auth_lifetime.obj `if test -f 'sa/tasks/ike_auth_lifetime.c'; then $(CYGPATH_W) 'sa/tasks/ike_auth_lifetime.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_auth_lifetime.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_lifetime.Tpo $(DEPDIR)/ike_auth_lifetime.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth_lifetime.c' object='ike_auth_lifetime.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_lifetime.obj `if test -f 'sa/tasks/ike_auth_lifetime.c'; then $(CYGPATH_W) 'sa/tasks/ike_auth_lifetime.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_auth_lifetime.c'; fi`
-
-ike_vendor.o: sa/tasks/ike_vendor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_vendor.o -MD -MP -MF $(DEPDIR)/ike_vendor.Tpo -c -o ike_vendor.o `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_vendor.Tpo $(DEPDIR)/ike_vendor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_vendor.c' object='ike_vendor.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_vendor.o `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
-
-ike_vendor.obj: sa/tasks/ike_vendor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_vendor.obj -MD -MP -MF $(DEPDIR)/ike_vendor.Tpo -c -o ike_vendor.obj `if test -f 'sa/tasks/ike_vendor.c'; then $(CYGPATH_W) 'sa/tasks/ike_vendor.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_vendor.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_vendor.Tpo $(DEPDIR)/ike_vendor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_vendor.c' object='ike_vendor.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_vendor.obj `if test -f 'sa/tasks/ike_vendor.c'; then $(CYGPATH_W) 'sa/tasks/ike_vendor.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_vendor.c'; fi`
-
-task.o: sa/tasks/task.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.o -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.o `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/task.c' object='task.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.o `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
-
-task.obj: sa/tasks/task.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.obj -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.obj `if test -f 'sa/tasks/task.c'; then $(CYGPATH_W) 'sa/tasks/task.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/task.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/task.c' object='task.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.obj `if test -f 'sa/tasks/task.c'; then $(CYGPATH_W) 'sa/tasks/task.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/task.c'; fi`
-
-credential_manager.o: credentials/credential_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.o -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.o `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.o `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
-
-credential_manager.obj: credentials/credential_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.obj -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.obj `if test -f 'credentials/credential_manager.c'; then $(CYGPATH_W) 'credentials/credential_manager.c'; else $(CYGPATH_W) '$(srcdir)/credentials/credential_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.obj `if test -f 'credentials/credential_manager.c'; then $(CYGPATH_W) 'credentials/credential_manager.c'; else $(CYGPATH_W) '$(srcdir)/credentials/credential_manager.c'; fi`
-
-auth_cfg_wrapper.o: credentials/sets/auth_cfg_wrapper.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.o -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.o `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg_wrapper.o `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
-
-auth_cfg_wrapper.obj: credentials/sets/auth_cfg_wrapper.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.obj -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.obj `if test -f 'credentials/sets/auth_cfg_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/auth_cfg_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/auth_cfg_wrapper.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg_wrapper.obj `if test -f 'credentials/sets/auth_cfg_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/auth_cfg_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/auth_cfg_wrapper.c'; fi`
-
-ocsp_response_wrapper.o: credentials/sets/ocsp_response_wrapper.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.o -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.o `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.o `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
-
-ocsp_response_wrapper.obj: credentials/sets/ocsp_response_wrapper.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.obj -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.obj `if test -f 'credentials/sets/ocsp_response_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/ocsp_response_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/ocsp_response_wrapper.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.obj `if test -f 'credentials/sets/ocsp_response_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/ocsp_response_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/ocsp_response_wrapper.c'; fi`
-
-cert_cache.o: credentials/sets/cert_cache.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.o -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.o `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.o `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
-
-cert_cache.obj: credentials/sets/cert_cache.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.obj -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.obj `if test -f 'credentials/sets/cert_cache.c'; then $(CYGPATH_W) 'credentials/sets/cert_cache.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/cert_cache.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.obj `if test -f 'credentials/sets/cert_cache.c'; then $(CYGPATH_W) 'credentials/sets/cert_cache.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/cert_cache.c'; fi`
-
-socket-raw.o: network/socket-raw.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket-raw.o -MD -MP -MF $(DEPDIR)/socket-raw.Tpo -c -o socket-raw.o `test -f 'network/socket-raw.c' || echo '$(srcdir)/'`network/socket-raw.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket-raw.Tpo $(DEPDIR)/socket-raw.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/socket-raw.c' object='socket-raw.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket-raw.o `test -f 'network/socket-raw.c' || echo '$(srcdir)/'`network/socket-raw.c
-
-socket-raw.obj: network/socket-raw.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket-raw.obj -MD -MP -MF $(DEPDIR)/socket-raw.Tpo -c -o socket-raw.obj `if test -f 'network/socket-raw.c'; then $(CYGPATH_W) 'network/socket-raw.c'; else $(CYGPATH_W) '$(srcdir)/network/socket-raw.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket-raw.Tpo $(DEPDIR)/socket-raw.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/socket-raw.c' object='socket-raw.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket-raw.obj `if test -f 'network/socket-raw.c'; then $(CYGPATH_W) 'network/socket-raw.c'; else $(CYGPATH_W) '$(srcdir)/network/socket-raw.c'; fi`
-
-socket.o: network/socket.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.o -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.o `test -f 'network/socket.c' || echo '$(srcdir)/'`network/socket.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/socket.c' object='socket.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket.o `test -f 'network/socket.c' || echo '$(srcdir)/'`network/socket.c
-
-socket.obj: network/socket.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.obj -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.obj `if test -f 'network/socket.c'; then $(CYGPATH_W) 'network/socket.c'; else $(CYGPATH_W) '$(srcdir)/network/socket.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/socket.c' object='socket.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket.obj `if test -f 'network/socket.c'; then $(CYGPATH_W) 'network/socket.c'; else $(CYGPATH_W) '$(srcdir)/network/socket.c'; fi`
-
-endpoint_notify.o: encoding/payloads/endpoint_notify.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.o -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.o `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/endpoint_notify.Tpo $(DEPDIR)/endpoint_notify.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/endpoint_notify.c' object='endpoint_notify.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o endpoint_notify.o `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
-
-endpoint_notify.obj: encoding/payloads/endpoint_notify.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.obj -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.obj `if test -f 'encoding/payloads/endpoint_notify.c'; then $(CYGPATH_W) 'encoding/payloads/endpoint_notify.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/endpoint_notify.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/endpoint_notify.Tpo $(DEPDIR)/endpoint_notify.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/endpoint_notify.c' object='endpoint_notify.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o endpoint_notify.obj `if test -f 'encoding/payloads/endpoint_notify.c'; then $(CYGPATH_W) 'encoding/payloads/endpoint_notify.c'; else $(CYGPATH_W) '$(srcdir)/encoding/payloads/endpoint_notify.c'; fi`
-
-initiate_mediation_job.o: processing/jobs/initiate_mediation_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT initiate_mediation_job.o -MD -MP -MF $(DEPDIR)/initiate_mediation_job.Tpo -c -o initiate_mediation_job.o `test -f 'processing/jobs/initiate_mediation_job.c' || echo '$(srcdir)/'`processing/jobs/initiate_mediation_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/initiate_mediation_job.Tpo $(DEPDIR)/initiate_mediation_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/initiate_mediation_job.c' object='initiate_mediation_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o initiate_mediation_job.o `test -f 'processing/jobs/initiate_mediation_job.c' || echo '$(srcdir)/'`processing/jobs/initiate_mediation_job.c
-
-initiate_mediation_job.obj: processing/jobs/initiate_mediation_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT initiate_mediation_job.obj -MD -MP -MF $(DEPDIR)/initiate_mediation_job.Tpo -c -o initiate_mediation_job.obj `if test -f 'processing/jobs/initiate_mediation_job.c'; then $(CYGPATH_W) 'processing/jobs/initiate_mediation_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/initiate_mediation_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/initiate_mediation_job.Tpo $(DEPDIR)/initiate_mediation_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/initiate_mediation_job.c' object='initiate_mediation_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o initiate_mediation_job.obj `if test -f 'processing/jobs/initiate_mediation_job.c'; then $(CYGPATH_W) 'processing/jobs/initiate_mediation_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/initiate_mediation_job.c'; fi`
-
-mediation_job.o: processing/jobs/mediation_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_job.o -MD -MP -MF $(DEPDIR)/mediation_job.Tpo -c -o mediation_job.o `test -f 'processing/jobs/mediation_job.c' || echo '$(srcdir)/'`processing/jobs/mediation_job.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_job.Tpo $(DEPDIR)/mediation_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/mediation_job.c' object='mediation_job.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_job.o `test -f 'processing/jobs/mediation_job.c' || echo '$(srcdir)/'`processing/jobs/mediation_job.c
-
-mediation_job.obj: processing/jobs/mediation_job.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_job.obj -MD -MP -MF $(DEPDIR)/mediation_job.Tpo -c -o mediation_job.obj `if test -f 'processing/jobs/mediation_job.c'; then $(CYGPATH_W) 'processing/jobs/mediation_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/mediation_job.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_job.Tpo $(DEPDIR)/mediation_job.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/mediation_job.c' object='mediation_job.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_job.obj `if test -f 'processing/jobs/mediation_job.c'; then $(CYGPATH_W) 'processing/jobs/mediation_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/mediation_job.c'; fi`
-
-connect_manager.o: sa/connect_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT connect_manager.o -MD -MP -MF $(DEPDIR)/connect_manager.Tpo -c -o connect_manager.o `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/connect_manager.Tpo $(DEPDIR)/connect_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/connect_manager.c' object='connect_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o connect_manager.o `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
-
-connect_manager.obj: sa/connect_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT connect_manager.obj -MD -MP -MF $(DEPDIR)/connect_manager.Tpo -c -o connect_manager.obj `if test -f 'sa/connect_manager.c'; then $(CYGPATH_W) 'sa/connect_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/connect_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/connect_manager.Tpo $(DEPDIR)/connect_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/connect_manager.c' object='connect_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o connect_manager.obj `if test -f 'sa/connect_manager.c'; then $(CYGPATH_W) 'sa/connect_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/connect_manager.c'; fi`
-
-mediation_manager.o: sa/mediation_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_manager.o -MD -MP -MF $(DEPDIR)/mediation_manager.Tpo -c -o mediation_manager.o `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_manager.Tpo $(DEPDIR)/mediation_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/mediation_manager.c' object='mediation_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.o `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
-
-mediation_manager.obj: sa/mediation_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_manager.obj -MD -MP -MF $(DEPDIR)/mediation_manager.Tpo -c -o mediation_manager.obj `if test -f 'sa/mediation_manager.c'; then $(CYGPATH_W) 'sa/mediation_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/mediation_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_manager.Tpo $(DEPDIR)/mediation_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/mediation_manager.c' object='mediation_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.obj `if test -f 'sa/mediation_manager.c'; then $(CYGPATH_W) 'sa/mediation_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/mediation_manager.c'; fi`
-
-ike_me.o: sa/tasks/ike_me.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.o -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.o `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.o `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
-
-ike_me.obj: sa/tasks/ike_me.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.obj -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.obj `if test -f 'sa/tasks/ike_me.c'; then $(CYGPATH_W) 'sa/tasks/ike_me.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_me.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.obj `if test -f 'sa/tasks/ike_me.c'; then $(CYGPATH_W) 'sa/tasks/ike_me.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_me.c'; fi`
-
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _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.
-$(RECURSIVE_TARGETS):
- @failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- list='$(SUBDIRS)'; 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"
-
-$(RECURSIVE_CLEAN_TARGETS):
- @failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- rev=''; for subdir in $$list; do \
- if test "$$subdir" = "."; then :; else \
- rev="$$subdir $$rev"; \
- fi; \
- done; \
- rev="$$rev ."; \
- target=`echo $@ | sed s/-recursive//`; \
- for subdir in $$rev; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done && test -z "$$fail"
-tags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
- done
-ctags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
- done
-
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -2364,23 +379,10 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
mkid -fID $$unique
tags: TAGS
-TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
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; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
@@ -2399,7 +401,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
fi; \
fi
ctags: CTAGS
-CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -2449,51 +451,22 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
check-am: all-am
-check: check-recursive
+check: check-am
all-am: Makefile $(PROGRAMS)
-installdirs: installdirs-recursive
-installdirs-am:
+installdirs:
for dir in "$(DESTDIR)$(ipsecdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
+install: 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-recursive
+installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
@@ -2510,95 +483,92 @@ 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."
-clean: clean-recursive
+clean: clean-am
clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \
mostlyclean-am
-distclean: distclean-recursive
+distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
-dvi: dvi-recursive
+dvi: dvi-am
dvi-am:
-html: html-recursive
+html: html-am
html-am:
-info: info-recursive
+info: info-am
info-am:
install-data-am: install-ipsecPROGRAMS
-install-dvi: install-dvi-recursive
+install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
-install-html: install-html-recursive
+install-html: install-html-am
install-html-am:
-install-info: install-info-recursive
+install-info: install-info-am
install-info-am:
install-man:
-install-pdf: install-pdf-recursive
+install-pdf: install-pdf-am
install-pdf-am:
-install-ps: install-ps-recursive
+install-ps: install-ps-am
install-ps-am:
installcheck-am:
-maintainer-clean: maintainer-clean-recursive
+maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-recursive
+mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-recursive
+pdf: pdf-am
pdf-am:
-ps: ps-recursive
+ps: ps-am
ps-am:
uninstall-am: uninstall-ipsecPROGRAMS
-.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
- install-am install-strip tags-recursive
-
-.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
- all all-am check check-am clean clean-generic \
- clean-ipsecPROGRAMS clean-libtool ctags ctags-recursive \
- 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-ipsecPROGRAMS install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs installdirs-am \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
- uninstall-ipsecPROGRAMS
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-ipsecPROGRAMS clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-ipsecPROGRAMS 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 uninstall uninstall-am uninstall-ipsecPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/charon/charon.c b/src/charon/charon.c
new file mode 100644
index 000000000..9b552fb62
--- /dev/null
+++ b/src/charon/charon.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+#ifdef HAVE_PRCTL
+#include <sys/prctl.h>
+#endif
+#define _POSIX_PTHREAD_SEMANTICS /* for two param sigwait on OpenSolaris */
+#include <signal.h>
+#undef _POSIX_PTHREAD_SEMANTICS
+#include <pthread.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <hydra.h>
+#include <daemon.h>
+
+#include <library.h>
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+
+/**
+ * PID file, in which charon stores its process id
+ */
+#define PID_FILE IPSEC_PIDDIR "/charon.pid"
+
+/**
+ * hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * 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);
+ }
+}
+
+/**
+ * Run the daemon and handle unix signals
+ */
+static void run()
+{
+ sigset_t set;
+
+ /* handle SIGINT, SIGHUP ans SIGTERM in this handler */
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGTERM);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ while (TRUE)
+ {
+ int sig;
+ int error;
+
+ error = sigwait(&set, &sig);
+ if (error)
+ {
+ DBG1(DBG_DMN, "error %d while waiting for a signal", error);
+ return;
+ }
+ switch (sig)
+ {
+ case SIGHUP:
+ {
+ DBG1(DBG_DMN, "signal of type SIGHUP received. Ignored");
+ break;
+ }
+ case SIGINT:
+ {
+ DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ case SIGTERM:
+ {
+ DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ default:
+ {
+ DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig);
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * drop daemon capabilities
+ */
+static bool drop_capabilities()
+{
+#ifdef HAVE_PRCTL
+ prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+#endif
+
+ if (setgid(charon->gid) != 0)
+ {
+ DBG1(DBG_DMN, "change to unprivileged group failed");
+ return FALSE;
+ }
+ if (setuid(charon->uid) != 0)
+ {
+ DBG1(DBG_DMN, "change to unprivileged user failed");
+ return FALSE;
+ }
+ if (!charon->drop_capabilities(charon))
+ {
+ DBG1(DBG_DMN, "unable to drop daemon capabilities");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * lookup UID and GID
+ */
+static bool lookup_uid_gid()
+{
+#ifdef IPSEC_USER
+ {
+ char buf[1024];
+ struct passwd passwd, *pwp;
+
+ if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
+ pwp == NULL)
+ {
+ DBG1(DBG_DMN, "resolving user '"IPSEC_USER"' failed");
+ return FALSE;
+ }
+ charon->uid = pwp->pw_uid;
+ }
+#endif
+#ifdef IPSEC_GROUP
+ {
+ char buf[1024];
+ struct group group, *grp;
+
+ if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
+ grp == NULL)
+ {
+ DBG1(DBG_DMN, "resolving group '"IPSEC_GROUP"' failed");
+ return FALSE;
+ }
+ charon->gid = grp->gr_gid;
+ }
+#endif
+ return TRUE;
+}
+
+/**
+ * Handle SIGSEGV/SIGILL signals raised by threads
+ */
+static void segv_handler(int signal)
+{
+ backtrace_t *backtrace;
+
+ DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr);
+ backtrace->destroy(backtrace);
+
+ DBG1(DBG_DMN, "killing ourself, received critical signal");
+ abort();
+}
+
+/**
+ * Check/create PID file, return TRUE if already running
+ */
+static bool check_pidfile()
+{
+ struct stat stb;
+ FILE *file;
+
+ if (stat(PID_FILE, &stb) == 0)
+ {
+ file = fopen(PID_FILE, "r");
+ if (file)
+ {
+ char buf[64];
+ pid_t pid = 0;
+
+ memset(buf, 0, sizeof(buf));
+ if (fread(buf, 1, sizeof(buf), file))
+ {
+ pid = atoi(buf);
+ }
+ fclose(file);
+ if (pid && kill(pid, 0) == 0)
+ { /* such a process is running */
+ return TRUE;
+ }
+ }
+ DBG1(DBG_DMN, "removing pidfile '"PID_FILE"', process not running");
+ unlink(PID_FILE);
+ }
+
+ /* create new pidfile */
+ file = fopen(PID_FILE, "w");
+ if (file)
+ {
+ fprintf(file, "%d\n", getpid());
+ ignore_result(fchown(fileno(file), charon->uid, charon->gid));
+ fclose(file);
+ }
+ return FALSE;
+}
+
+/**
+ * print command line usage and exit
+ */
+static void usage(const char *msg)
+{
+ if (msg != NULL && *msg != '\0')
+ {
+ fprintf(stderr, "%s\n", msg);
+ }
+ fprintf(stderr, "Usage: charon\n"
+ " [--help]\n"
+ " [--version]\n"
+ " [--use-syslog]\n"
+ " [--debug-<type> <level>]\n"
+ " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib)\n"
+ " <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
+ " 2 = controlmore, 3 = raw, 4 = private)\n"
+ "\n"
+ );
+ exit(msg == NULL? 0 : 1);
+}
+
+/**
+ * Main function, starts the daemon.
+ */
+int main(int argc, char *argv[])
+{
+ struct sigaction action;
+ bool use_syslog = FALSE;
+ level_t levels[DBG_MAX];
+ int group, status = SS_RC_INITIALIZATION_FAILED;
+
+ /* logging for library during initialization, as we have no bus yet */
+ dbg = dbg_stderr;
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ library_deinit();
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+
+ if (lib->integrity &&
+ !lib->integrity->check_file(lib->integrity, "charon", argv[0]))
+ {
+ dbg_stderr(DBG_DMN, 1, "integrity check of charon failed");
+ library_deinit();
+ exit(SS_RC_DAEMON_INTEGRITY);
+ }
+
+ if (!libhydra_init("charon"))
+ {
+ dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
+ libhydra_deinit();
+ library_deinit();
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ if (!libcharon_init())
+ {
+ dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
+ goto deinit;
+ }
+
+ /* use CTRL loglevel for default */
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ levels[group] = LEVEL_CTRL;
+ }
+
+ /* handle arguments */
+ for (;;)
+ {
+ struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "use-syslog", no_argument, NULL, 'l' },
+ /* TODO: handle "debug-all" */
+ { "debug-dmn", required_argument, &group, DBG_DMN },
+ { "debug-mgr", required_argument, &group, DBG_MGR },
+ { "debug-ike", required_argument, &group, DBG_IKE },
+ { "debug-chd", required_argument, &group, DBG_CHD },
+ { "debug-job", required_argument, &group, DBG_JOB },
+ { "debug-cfg", required_argument, &group, DBG_CFG },
+ { "debug-knl", required_argument, &group, DBG_KNL },
+ { "debug-net", required_argument, &group, DBG_NET },
+ { "debug-enc", required_argument, &group, DBG_ENC },
+ { "debug-lib", required_argument, &group, DBG_LIB },
+ { 0,0,0,0 }
+ };
+
+ int c = getopt_long(argc, argv, "", long_opts, NULL);
+ switch (c)
+ {
+ case EOF:
+ break;
+ case 'h':
+ usage(NULL);
+ break;
+ case 'v':
+ printf("Linux strongSwan %s\n", VERSION);
+ status = 0;
+ goto deinit;
+ case 'l':
+ use_syslog = TRUE;
+ continue;
+ case 0:
+ /* option is in group */
+ levels[group] = atoi(optarg);
+ continue;
+ default:
+ usage("");
+ break;
+ }
+ break;
+ }
+
+ if (!lookup_uid_gid())
+ {
+ dbg_stderr(DBG_DMN, 1, "invalid uid/gid - aborting charon");
+ goto deinit;
+ }
+
+ /* initialize daemon */
+ if (!charon->initialize(charon, use_syslog, levels))
+ {
+ DBG1(DBG_DMN, "initialization failed - aborting charon");
+ goto deinit;
+ }
+
+ if (check_pidfile())
+ {
+ DBG1(DBG_DMN, "charon already running (\""PID_FILE"\" exists)");
+ status = -1;
+ goto deinit;
+ }
+
+ if (!drop_capabilities())
+ {
+ DBG1(DBG_DMN, "capability dropping failed - aborting charon");
+ goto deinit;
+ }
+
+ /* add handler for SEGV and ILL,
+ * INT, TERM and HUP are handled by sigwait() in run() */
+ action.sa_handler = segv_handler;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGINT);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaction(SIGSEGV, &action, NULL);
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
+
+ /* start daemon (i.e. the threads in the thread-pool) */
+ charon->start(charon);
+
+ /* main thread goes to run loop */
+ run();
+
+ /* normal termination, cleanup and exit */
+ unlink(PID_FILE);
+ status = 0;
+
+deinit:
+ libcharon_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return status;
+}
+
diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am
index d0413e64e..27d615dab 100644
--- a/src/checksum/Makefile.am
+++ b/src/checksum/Makefile.am
@@ -5,17 +5,28 @@ nodist_libchecksum_la_SOURCES = checksum.c
libchecksum_la_LDFLAGS = -module -avoid-version
checksum_builder_SOURCES = checksum_builder.c
-checksum_builder_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+checksum_builder_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ $(DLLIB)
BUILT_SOURCES = checksum.c
CLEANFILES = checksum.c
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-libs = $(shell find $(top_builddir)/src/libstrongswan $(top_builddir)/src/charon \
+libs = $(shell find $(top_builddir)/src/libstrongswan \
+ $(top_builddir)/src/libcharon \
+ $(top_builddir)/src/libhydra \
-name 'libstrongswan*.so')
+if USE_LIBHYDRA
+ libs += $(top_builddir)/src/libhydra/.libs/libhydra.so
+endif
+
if USE_CHARON
+ libs += $(top_builddir)/src/libcharon/.libs/libcharon.so
libs += $(top_builddir)/src/charon/.libs/charon
endif
@@ -30,7 +41,7 @@ if USE_TOOLS
endif
if USE_ATTR_SQL
- libs += $(top_builddir)/src/libstrongswan/plugins/attr_sql/.libs/pool
+ libs += $(top_builddir)/src/libhydra/plugins/attr_sql/.libs/pool
endif
checksum.c : checksum_builder $(libs)
diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in
index 6769c2601..3e0ab1e69 100644
--- a/src/checksum/Makefile.in
+++ b/src/checksum/Makefile.in
@@ -36,13 +36,15 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = checksum_builder$(EXEEXT)
-@USE_CHARON_TRUE@am__append_1 = $(top_builddir)/src/charon/.libs/charon
-@USE_PLUTO_TRUE@am__append_2 = $(top_builddir)/src/pluto/.libs/pluto
-@USE_TOOLS_TRUE@am__append_3 = \
+@USE_LIBHYDRA_TRUE@am__append_1 = $(top_builddir)/src/libhydra/.libs/libhydra.so
+@USE_CHARON_TRUE@am__append_2 = $(top_builddir)/src/libcharon/.libs/libcharon.so \
+@USE_CHARON_TRUE@ $(top_builddir)/src/charon/.libs/charon
+@USE_PLUTO_TRUE@am__append_3 = $(top_builddir)/src/pluto/.libs/pluto
+@USE_TOOLS_TRUE@am__append_4 = \
@USE_TOOLS_TRUE@ $(top_builddir)/src/openac/.libs/openac \
@USE_TOOLS_TRUE@ $(top_builddir)/src/pki/.libs/pki \
@USE_TOOLS_TRUE@ $(top_builddir)/src/scepclient/.libs/scepclient
-@USE_ATTR_SQL_TRUE@am__append_4 = $(top_builddir)/src/libstrongswan/plugins/attr_sql/.libs/pool
+@USE_ATTR_SQL_TRUE@am__append_5 = $(top_builddir)/src/libhydra/plugins/attr_sql/.libs/pool
subdir = src/checksum
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -91,8 +93,12 @@ libchecksum_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
PROGRAMS = $(noinst_PROGRAMS)
am_checksum_builder_OBJECTS = checksum_builder.$(OBJEXT)
checksum_builder_OBJECTS = $(am_checksum_builder_OBJECTS)
+am__DEPENDENCIES_1 =
checksum_builder_DEPENDENCIES = \
- $(top_builddir)/src/libstrongswan/libstrongswan.la
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -231,6 +237,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -269,15 +276,20 @@ ipsec_LTLIBRARIES = libchecksum.la
nodist_libchecksum_la_SOURCES = checksum.c
libchecksum_la_LDFLAGS = -module -avoid-version
checksum_builder_SOURCES = checksum_builder.c
-checksum_builder_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+checksum_builder_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ $(DLLIB)
+
BUILT_SOURCES = checksum.c
CLEANFILES = checksum.c
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
libs = $(shell find $(top_builddir)/src/libstrongswan \
- $(top_builddir)/src/charon -name 'libstrongswan*.so') \
- $(am__append_1) $(am__append_2) $(am__append_3) \
- $(am__append_4)
+ $(top_builddir)/src/libcharon $(top_builddir)/src/libhydra \
+ -name 'libstrongswan*.so') $(am__append_1) $(am__append_2) \
+ $(am__append_3) $(am__append_4) $(am__append_5)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c
index 54f4539ff..b68a25a19 100644
--- a/src/checksum/checksum_builder.c
+++ b/src/checksum/checksum_builder.c
@@ -13,17 +13,13 @@
* for more details.
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <library.h>
-/* we need to fake some charon symbols to dlopen() its plugins */
-void *charon, *eap_type_names, *auth_class_names, *protocol_id_names,
-*action_names, *ipsec_mode_names, *ike_sa_state_names, *child_sa_state_names,
-*policy_dir_names, *ipcomp_transform_names, *debug_names, *controller_cb_empty;
-
int main(int argc, char* argv[])
{
int i;
@@ -62,12 +58,30 @@ int main(int argc, char* argv[])
name[strlen(name) - 3] = '"';
name[strlen(name) - 2] = ',';
name[strlen(name) - 1] = '\0';
- sname = "plugin_create";
+ if (asprintf(&sname, "%.*s_plugin_create", strlen(name) - 2,
+ name) < 0)
+ {
+ fprintf(stderr, "failed to format plugin constructor "
+ "for '%s', ignored", path);
+ free(name);
+ continue;
+ }
+ translate(sname, "-", "_");
}
else if (strstr(path, "libstrongswan.so"))
{
name = strdup("libstrongswan\",");
- sname = "library_init";
+ sname = strdup("library_init");
+ }
+ else if (strstr(path, "libhydra.so"))
+ {
+ name = strdup("libhydra\",");
+ sname = strdup("libhydra_init");
+ }
+ else if (strstr(path, "libcharon.so"))
+ {
+ name = strdup("libcharon\",");
+ sname = strdup("libcharon_init");
}
else if (strstr(path, "pool"))
{
@@ -126,6 +140,7 @@ int main(int argc, char* argv[])
name, fsize, fsum, ssize, ssum);
fprintf(stderr, "\"%-20s%7u / 0x%08x %6u / 0x%08x\n",
name, fsize, fsum, ssize, ssum);
+ free(sname);
free(name);
}
printf("};\n");
diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in
index 8bc08e2c1..36fdbff28 100644
--- a/src/dumm/Makefile.in
+++ b/src/dumm/Makefile.in
@@ -226,6 +226,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/dumm/bridge.c b/src/dumm/bridge.c
index 592fecefd..9c63beed9 100644
--- a/src/dumm/bridge.c
+++ b/src/dumm/bridge.c
@@ -69,8 +69,8 @@ static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
{
if (br_del_interface(this->name, iface->get_hostif(iface)) != 0)
{
- DBG1("removing iface '%s' from bridge '%s' in kernel failed: %m",
- iface->get_hostif(iface), this->name);
+ DBG1(DBG_LIB, "removing iface '%s' from bridge '%s' in kernel"
+ " failed: %m", iface->get_hostif(iface), this->name);
}
else
{
@@ -83,8 +83,8 @@ static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
}
if (iface != current)
{
- DBG1("iface '%s' not found on bridge '%s'", iface->get_hostif(iface),
- this->name);
+ DBG1(DBG_LIB, "iface '%s' not found on bridge '%s'",
+ iface->get_hostif(iface), this->name);
}
enumerator->destroy(enumerator);
return good;
@@ -97,7 +97,7 @@ static bool connect_iface(private_bridge_t *this, iface_t *iface)
{
if (br_add_interface(this->name, iface->get_hostif(iface)) != 0)
{
- DBG1("adding iface '%s' to bridge '%s' failed: %m",
+ DBG1(DBG_LIB, "adding iface '%s' to bridge '%s' failed: %m",
iface->get_hostif(iface), this->name);
return FALSE;
}
@@ -124,7 +124,8 @@ static void destroy(private_bridge_t *this)
{
if (br_del_interface(this->name, iface->get_hostif(iface)) != 0)
{
- DBG1("disconnecting iface '%s' failed: %m", iface->get_hostif(iface));
+ DBG1(DBG_LIB, "disconnecting iface '%s' failed: %m",
+ iface->get_hostif(iface));
}
iface->set_bridge(iface, NULL);
}
@@ -133,7 +134,8 @@ static void destroy(private_bridge_t *this)
iface_control(this->name, FALSE);
if (br_del_bridge(this->name) != 0)
{
- DBG1("deleting bridge '%s' from kernel failed: %m", this->name);
+ DBG1(DBG_LIB, "deleting bridge '%s' from kernel failed: %m",
+ this->name);
}
free(this->name);
free(this);
@@ -154,7 +156,7 @@ bridge_t *bridge_create(char *name)
{
if (br_init() != 0)
{
- DBG1("libbridge initialization failed: %m");
+ DBG1(DBG_LIB, "libbridge initialization failed: %m");
return NULL;
}
}
@@ -168,13 +170,13 @@ bridge_t *bridge_create(char *name)
if (br_add_bridge(name) != 0)
{
- DBG1("creating bridge '%s' failed: %m", name);
+ DBG1(DBG_LIB, "creating bridge '%s' failed: %m", name);
free(this);
return NULL;
}
if (!iface_control(name, TRUE))
{
- DBG1("bringing bridge '%s' up failed: %m", name);
+ DBG1(DBG_LIB, "bringing bridge '%s' up failed: %m", name);
}
this->name = strdup(name);
diff --git a/src/dumm/cowfs.c b/src/dumm/cowfs.c
index f7b6b0cf3..70767890b 100644
--- a/src/dumm/cowfs.c
+++ b/src/dumm/cowfs.c
@@ -493,12 +493,12 @@ static int cowfs_link(const char *from, const char *to)
if (!clone_path(rd, wr, to))
{
- DBG1("cloning path '%s' failed", to);
+ DBG1(DBG_LIB, "cloning path '%s' failed", to);
return -errno;
}
if (linkat(rd, from, wr, to, 0) < 0)
{
- DBG1("linking '%s' to '%s' failed", from, to);
+ DBG1(DBG_LIB, "linking '%s' to '%s' failed", from, to);
return -errno;
}
return 0;
@@ -777,7 +777,7 @@ static bool set_overlay(private_cowfs_t *this, char *path)
this->over_fd = open(path, O_RDONLY | O_DIRECTORY);
if (this->over_fd < 0)
{
- DBG1("failed to open overlay directory '%s': %m", path);
+ DBG1(DBG_LIB, "failed to open overlay directory '%s': %m", path);
return FALSE;
}
this->over = strdup(path);
@@ -821,14 +821,14 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
this->master_fd = open(master, O_RDONLY | O_DIRECTORY);
if (this->master_fd < 0)
{
- DBG1("failed to open master filesystem '%s'", master);
+ DBG1(DBG_LIB, "failed to open master filesystem '%s'", master);
free(this);
return NULL;
}
this->host_fd = open(host, O_RDONLY | O_DIRECTORY);
if (this->host_fd < 0)
{
- DBG1("failed to open host filesystem '%s'", host);
+ DBG1(DBG_LIB, "failed to open host filesystem '%s'", host);
close(this->master_fd);
free(this);
return NULL;
@@ -838,7 +838,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
this->chan = fuse_mount(mount, &args);
if (this->chan == NULL)
{
- DBG1("mounting cowfs FUSE on '%s' failed", mount);
+ DBG1(DBG_LIB, "mounting cowfs FUSE on '%s' failed", mount);
close(this->master_fd);
close(this->host_fd);
free(this);
@@ -849,7 +849,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
sizeof(cowfs_operations), this);
if (this->fuse == NULL)
{
- DBG1("creating cowfs FUSE handle failed");
+ DBG1(DBG_LIB, "creating cowfs FUSE handle failed");
close(this->master_fd);
close(this->host_fd);
fuse_unmount(mount, this->chan);
@@ -865,7 +865,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
this->thread = thread_create((thread_main_t)fuse_loop, this->fuse);
if (!this->thread)
{
- DBG1("creating thread to handle FUSE failed");
+ DBG1(DBG_LIB, "creating thread to handle FUSE failed");
fuse_unmount(mount, this->chan);
free(this->mount);
free(this->master);
diff --git a/src/dumm/dumm.c b/src/dumm/dumm.c
index 0e8ab43f3..7ec340089 100644
--- a/src/dumm/dumm.c
+++ b/src/dumm/dumm.c
@@ -162,7 +162,7 @@ static bool load_template(private_dumm_t *this, char *dir)
}
if (strlen(dir) > PATH_MAX)
{
- DBG1("template directory string '%s' is too long", dir);
+ DBG1(DBG_LIB, "template directory string '%s' is too long", dir);
return FALSE;
}
@@ -175,7 +175,8 @@ static bool load_template(private_dumm_t *this, char *dir)
{ /* does not exist, create template */
if (!mkdir_p(this->template, PERME))
{
- DBG1("creating template directory '%s' failed: %m", this->template);
+ DBG1(DBG_LIB, "creating template directory '%s' failed: %m",
+ this->template);
return FALSE;
}
}
@@ -302,7 +303,8 @@ static void load_guests(private_dumm_t *this)
}
else
{
- DBG1("loading guest in directory '%s' failed, skipped", ent->d_name);
+ DBG1(DBG_LIB, "loading guest in directory '%s' failed, skipped",
+ ent->d_name);
}
}
closedir(dir);
@@ -360,7 +362,8 @@ dumm_t *dumm_create(char *dir)
if (this->dir == NULL || this->guest_dir == NULL ||
(mkdir(this->guest_dir, PERME) < 0 && errno != EEXIST))
{
- DBG1("creating guest directory '%s' failed: %m", this->guest_dir);
+ DBG1(DBG_LIB, "creating guest directory '%s' failed: %m",
+ this->guest_dir);
destroy(this);
return NULL;
}
diff --git a/src/dumm/guest.c b/src/dumm/guest.c
index 112adb441..ebd87769a 100644
--- a/src/dumm/guest.c
+++ b/src/dumm/guest.c
@@ -100,7 +100,8 @@ static iface_t* create_iface(private_guest_t *this, char *name)
if (this->state != GUEST_RUNNING)
{
- DBG1("guest '%s' not running, unable to add interface", this->name);
+ DBG1(DBG_LIB, "guest '%s' not running, unable to add interface",
+ this->name);
return NULL;
}
@@ -109,7 +110,8 @@ static iface_t* create_iface(private_guest_t *this, char *name)
{
if (streq(name, iface->get_guestif(iface)))
{
- DBG1("guest '%s' already has an interface '%s'", this->name, name);
+ DBG1(DBG_LIB, "guest '%s' already has an interface '%s'",
+ this->name, name);
enumerator->destroy(enumerator);
return NULL;
}
@@ -251,7 +253,8 @@ static bool start(private_guest_t *this, invoke_function_t invoke, void* data,
if (this->state != GUEST_STOPPED)
{
- DBG1("unable to start guest in state %N", guest_state_names, this->state);
+ DBG1(DBG_LIB, "unable to start guest in state %N", guest_state_names,
+ this->state);
return FALSE;
}
this->state = GUEST_STARTING;
@@ -284,7 +287,7 @@ static bool start(private_guest_t *this, invoke_function_t invoke, void* data,
this->mconsole = mconsole_create(notify, idle);
if (this->mconsole == NULL)
{
- DBG1("opening mconsole at '%s' failed, stopping guest", buf);
+ DBG1(DBG_LIB, "opening mconsole at '%s' failed, stopping guest", buf);
stop(this, NULL);
return FALSE;
}
@@ -315,7 +318,8 @@ static bool load_template(private_guest_t *this, char *path)
{
if (!mkdir_p(dir, PERME))
{
- DBG1("creating overlay for guest '%s' failed: %m", this->name);
+ DBG1(DBG_LIB, "creating overlay for guest '%s' failed: %m",
+ this->name);
return FALSE;
}
}
@@ -595,7 +599,7 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
this->dir = open(this->dirname, O_DIRECTORY, PERME);
if (this->dir < 0)
{
- DBG1("opening guest directory '%s' failed: %m", this->dirname);
+ DBG1(DBG_LIB, "opening guest directory '%s' failed: %m", this->dirname);
free(this->dirname);
free(this);
return NULL;
@@ -647,7 +651,7 @@ guest_t *guest_create(char *parent, char *name, char *kernel,
if (!make_symlink(this, master, MASTER_DIR) ||
!make_symlink(this, kernel, KERNEL_FILE))
{
- DBG1("creating master/kernel symlink failed: %m");
+ DBG1(DBG_LIB, "creating master/kernel symlink failed: %m");
destroy(this);
return NULL;
}
@@ -655,7 +659,7 @@ guest_t *guest_create(char *parent, char *name, char *kernel,
if (mkdirat(this->dir, UNION_DIR, PERME) != 0 ||
mkdirat(this->dir, DIFF_DIR, PERME) != 0)
{
- DBG1("unable to create directories for '%s': %m", name);
+ DBG1(DBG_LIB, "unable to create directories for '%s': %m", name);
destroy(this);
return NULL;
}
diff --git a/src/dumm/iface.c b/src/dumm/iface.c
index 9910c392e..1b5b7d717 100644
--- a/src/dumm/iface.c
+++ b/src/dumm/iface.c
@@ -196,7 +196,7 @@ static bool destroy_tap(private_iface_t *this)
if (!iface_control(this->hostif, FALSE))
{
- DBG1("bringing iface down failed: %m");
+ DBG1(DBG_LIB, "bringing iface down failed: %m");
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -205,13 +205,13 @@ static bool destroy_tap(private_iface_t *this)
tap = open(TAP_DEVICE, O_RDWR);
if (tap < 0)
{
- DBG1("unable to open tap device %s: %m", TAP_DEVICE);
+ DBG1(DBG_LIB, "unable to open tap device %s: %m", TAP_DEVICE);
return FALSE;
}
if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
ioctl(tap, TUNSETPERSIST, 0) < 0)
{
- DBG1("removing %s failed: %m", this->hostif);
+ DBG1(DBG_LIB, "removing %s failed: %m", this->hostif);
close(tap);
return FALSE;
}
@@ -235,14 +235,14 @@ static char* create_tap(private_iface_t *this)
tap = open(TAP_DEVICE, O_RDWR);
if (tap < 0)
{
- DBG1("unable to open tap device %s: %m", TAP_DEVICE);
+ DBG1(DBG_LIB, "unable to open tap device %s: %m", TAP_DEVICE);
return NULL;
}
if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
ioctl(tap, TUNSETPERSIST, 1) < 0 ||
ioctl(tap, TUNSETOWNER, 0))
{
- DBG1("creating new tap device failed: %m");
+ DBG1(DBG_LIB, "creating new tap device failed: %m");
close(tap);
return NULL;
}
@@ -299,7 +299,7 @@ iface_t *iface_create(char *name, guest_t *guest, mconsole_t *mconsole)
}
if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif))
{
- DBG1("creating interface '%s' in guest failed", this->guestif);
+ DBG1(DBG_LIB, "creating interface '%s' in guest failed", this->guestif);
destroy_tap(this);
free(this->guestif);
free(this->hostif);
@@ -308,7 +308,7 @@ iface_t *iface_create(char *name, guest_t *guest, mconsole_t *mconsole)
}
if (!iface_control(this->hostif, TRUE))
{
- DBG1("bringing iface '%s' up failed: %m", this->hostif);
+ DBG1(DBG_LIB, "bringing iface '%s' up failed: %m", this->hostif);
}
return &this->public;
}
diff --git a/src/dumm/mconsole.c b/src/dumm/mconsole.c
index 35984bdd5..7d982a54c 100644
--- a/src/dumm/mconsole.c
+++ b/src/dumm/mconsole.c
@@ -120,7 +120,7 @@ static int request(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
if (len < 0)
{
- DBG1("sending mconsole command to UML failed: %m");
+ DBG1(DBG_LIB, "sending mconsole command to UML failed: %m");
return -1;
}
do
@@ -136,7 +136,7 @@ static int request(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
}
if (len < 0)
{
- DBG1("receiving from mconsole failed: %m");
+ DBG1(DBG_LIB, "receiving from mconsole failed: %m");
return -1;
}
if (len > 0)
@@ -149,7 +149,7 @@ static int request(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
{
if (reply.len && *reply.data)
{
- DBG1("received mconsole error %d: %.*s",
+ DBG1(DBG_LIB, "received mconsole error %d: %.*s",
reply.err, reply.len, reply.data);
}
break;
@@ -245,7 +245,7 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
this->notify = socket(AF_UNIX, SOCK_DGRAM, 0);
if (this->notify < 0)
{
- DBG1("opening mconsole notify socket failed: %m");
+ DBG1(DBG_LIB, "opening mconsole notify socket failed: %m");
return FALSE;
}
memset(&addr, 0, sizeof(addr));
@@ -253,7 +253,8 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
strncpy(addr.sun_path, nsock, sizeof(addr.sun_path));
if (bind(this->notify, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
- DBG1("binding mconsole notify socket to '%s' failed: %m", nsock);
+ DBG1(DBG_LIB, "binding mconsole notify socket to '%s' failed: %m",
+ nsock);
close(this->notify);
return FALSE;
}
@@ -273,7 +274,7 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
if (len < 0 || len >= sizeof(notify))
{
- DBG1("reading from mconsole notify socket failed: %m");
+ DBG1(DBG_LIB, "reading from mconsole notify socket failed: %m");
close(this->notify);
unlink(nsock);
return FALSE;
@@ -282,8 +283,8 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
notify.version != MCONSOLE_VERSION ||
notify.type != MCONSOLE_SOCKET)
{
- DBG1("received unexpected message from mconsole notify socket: %b",
- &notify, sizeof(notify));
+ DBG1(DBG_LIB, "received unexpected message from mconsole notify"
+ " socket: %b", &notify, sizeof(notify));
close(this->notify);
unlink(nsock);
return FALSE;
@@ -304,7 +305,7 @@ static bool setup_console(private_mconsole_t *this)
this->console = socket(AF_UNIX, SOCK_DGRAM, 0);
if (this->console < 0)
{
- DBG1("opening mconsole socket failed: %m");
+ DBG1(DBG_LIB, "opening mconsole socket failed: %m");
return FALSE;
}
memset(&addr, 0, sizeof(addr));
@@ -313,7 +314,8 @@ static bool setup_console(private_mconsole_t *this)
getpid(), this->console);
if (bind(this->console, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
- DBG1("binding mconsole socket to '%s' failed: %m", &addr.sun_path[1]);
+ DBG1(DBG_LIB, "binding mconsole socket to '%s' failed: %m",
+ &addr.sun_path[1]);
close(this->console);
return FALSE;
}
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 6aeb84bae..9edad1141 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -1,3 +1,3 @@
EXTRA_DIST = linux/ipsec.h linux/netlink.h linux/rtnetlink.h \
linux/pfkeyv2.h linux/udp.h linux/xfrm.h linux/types.h \
- sys/queue.h
+ linux/jhash.h sys/queue.h
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 762b32649..720ba3a11 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -172,6 +172,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -208,7 +209,7 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
EXTRA_DIST = linux/ipsec.h linux/netlink.h linux/rtnetlink.h \
linux/pfkeyv2.h linux/udp.h linux/xfrm.h linux/types.h \
- sys/queue.h
+ linux/jhash.h sys/queue.h
all: all-am
diff --git a/src/include/linux/jhash.h b/src/include/linux/jhash.h
new file mode 100644
index 000000000..2a2f99fbc
--- /dev/null
+++ b/src/include/linux/jhash.h
@@ -0,0 +1,143 @@
+#ifndef _LINUX_JHASH_H
+#define _LINUX_JHASH_H
+
+/* jhash.h: Jenkins hash support.
+ *
+ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
+ *
+ * http://burtleburtle.net/bob/hash/
+ *
+ * These are the credits from Bob's sources:
+ *
+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ * hash(), hash2(), hash3, and mix() are externally useful functions.
+ * Routines to test the hash are included if SELF_TEST is defined.
+ * You can use this free for any purpose. It has no warranty.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ *
+ * I've modified Bob's hash to be useful in the Linux kernel, and
+ * any bugs present are surely my fault. -DaveM
+ */
+
+/* NOTE: Arguments are modified. */
+#define __jhash_mix(a, b, c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/* The golden ration: an arbitrary value */
+#define JHASH_GOLDEN_RATIO 0x9e3779b9
+
+/* The most generic version, hashes an arbitrary sequence
+ * of bytes. No alignment or length assumptions are made about
+ * the input key.
+ */
+static inline u32 jhash(const void *key, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+ const u8 *k = key;
+
+ len = length;
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+
+ while (len >= 12) {
+ a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
+ b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
+ c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
+
+ __jhash_mix(a,b,c);
+
+ k += 12;
+ len -= 12;
+ }
+
+ c += length;
+ switch (len) {
+ case 11: c += ((u32)k[10]<<24);
+ case 10: c += ((u32)k[9]<<16);
+ case 9 : c += ((u32)k[8]<<8);
+ case 8 : b += ((u32)k[7]<<24);
+ case 7 : b += ((u32)k[6]<<16);
+ case 6 : b += ((u32)k[5]<<8);
+ case 5 : b += k[4];
+ case 4 : a += ((u32)k[3]<<24);
+ case 3 : a += ((u32)k[2]<<16);
+ case 2 : a += ((u32)k[1]<<8);
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+/* A special optimized version that handles 1 or more of u32s.
+ * The length parameter here is the number of u32s in the key.
+ */
+static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+ len = length;
+
+ while (len >= 3) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ __jhash_mix(a, b, c);
+ k += 3; len -= 3;
+ }
+
+ c += length * 4;
+
+ switch (len) {
+ case 2 : b += k[1];
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+
+/* A special ultra-optimized versions that knows they are hashing exactly
+ * 3, 2 or 1 word(s).
+ *
+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
+ * done at the end is not done here.
+ */
+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+{
+ a += JHASH_GOLDEN_RATIO;
+ b += JHASH_GOLDEN_RATIO;
+ c += initval;
+
+ __jhash_mix(a, b, c);
+
+ return c;
+}
+
+static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
+{
+ return jhash_3words(a, b, 0, initval);
+}
+
+static inline u32 jhash_1word(u32 a, u32 initval)
+{
+ return jhash_3words(a, 0, 0, initval);
+}
+
+#endif /* _LINUX_JHASH_H */
diff --git a/src/include/linux/pfkeyv2.h b/src/include/linux/pfkeyv2.h
index b4b0712a4..7379d1a94 100644
--- a/src/include/linux/pfkeyv2.h
+++ b/src/include/linux/pfkeyv2.h
@@ -315,6 +315,7 @@ struct sadb_x_kmaddress {
#define SADB_X_EALG_AES_GCM_ICV12 19
#define SADB_X_EALG_AES_GCM_ICV16 20
#define SADB_X_EALG_CAMELLIACBC 22
+#define SADB_X_EALG_NULL_AES_GMAC 23
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in
index ff88ed1ff..3834b672a 100644
--- a/src/ipsec/Makefile.in
+++ b/src/ipsec/Makefile.in
@@ -200,6 +200,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/ipsec/ipsec.in b/src/ipsec/ipsec.in
index 1da3c2d90..0bddc201a 100755
--- a/src/ipsec/ipsec.in
+++ b/src/ipsec/ipsec.in
@@ -2,13 +2,13 @@
# prefix command to run stuff from our programs directory
# Copyright (C) 1998-2002 Henry Spencer.
# Copyright (C) 2006 Andreas Steffen
-# Copyright (C) 2006 Martin Willi
-#
+# Copyright (C) 2006 Martin Willi
+#
# 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
@@ -67,7 +67,7 @@ case "$1" in
echo " rereadacerts|rereadcrls|rereadall"
echo " purgeocsp|purgeike"
echo " scencrypt|scdecrypt <value> [--inbase <base>] [--outbase <base>] [--keyid <id>]"
- echo " openac"
+ echo " openac"
echo " pluto"
echo " scepclient"
echo " secrets"
@@ -138,17 +138,26 @@ listcards|rereadgroups)
$IPSEC_WHACK "$@" "--$op"
rc="$?"
fi
- if [ -e $IPSEC_CHARON_PID ]
- then
- exit 3
- else
- exit 7
- fi
+ if [ -e $IPSEC_CHARON_PID ]
+ then
+ exit 3
+ else
+ exit 7
+ fi
;;
leases)
op="$1"
rc=7
shift
+ if [ -e $IPSEC_PLUTO_PID ]
+ then
+ case "$#" in
+ 0) $IPSEC_WHACK "--$op" ;;
+ 1) $IPSEC_WHACK "--$op" --name "$1" ;;
+ *) $IPSEC_WHACK "--$op" --name "$1" --lease-addr "$2" ;;
+ esac
+ rc="$?"
+ fi
if [ -e $IPSEC_CHARON_PID ]
then
case "$#" in
@@ -330,7 +339,7 @@ stop)
fi
fi
else
- echo "Stopping strongSwan IPsec failed: starter is not running" >&2
+ echo "Stopping strongSwan IPsec failed: starter is not running" >&2
fi
if [ -d /var/lock/subsys ]; then
rm -f /var/lock/subsys/ipsec
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
new file mode 100644
index 000000000..d473b455e
--- /dev/null
+++ b/src/libcharon/Android.mk
@@ -0,0 +1,174 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+bus/bus.c bus/bus.h \
+bus/listeners/listener.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 config/peer_cfg.h \
+config/proposal.c config/proposal.h \
+config/auth_cfg.c config/auth_cfg.h \
+control/controller.c control/controller.h \
+daemon.c daemon.h \
+encoding/generator.c encoding/generator.h \
+encoding/message.c encoding/message.h \
+encoding/parser.c encoding/parser.h \
+encoding/payloads/auth_payload.c encoding/payloads/auth_payload.h \
+encoding/payloads/cert_payload.c encoding/payloads/cert_payload.h \
+encoding/payloads/certreq_payload.c encoding/payloads/certreq_payload.h \
+encoding/payloads/configuration_attribute.c encoding/payloads/configuration_attribute.h \
+encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
+encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
+encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
+encoding/payloads/encodings.c encoding/payloads/encodings.h \
+encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
+encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
+encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
+encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
+encoding/payloads/nonce_payload.c encoding/payloads/nonce_payload.h \
+encoding/payloads/notify_payload.c encoding/payloads/notify_payload.h \
+encoding/payloads/payload.c encoding/payloads/payload.h \
+encoding/payloads/proposal_substructure.c encoding/payloads/proposal_substructure.h \
+encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
+encoding/payloads/traffic_selector_substructure.c encoding/payloads/traffic_selector_substructure.h \
+encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
+encoding/payloads/transform_substructure.c encoding/payloads/transform_substructure.h \
+encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
+encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
+encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
+kernel/kernel_interface.c kernel/kernel_interface.h \
+kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+kernel/kernel_net.h \
+network/packet.c network/packet.h \
+network/receiver.c network/receiver.h \
+network/sender.c network/sender.h \
+network/socket_manager.c network/socket_manager.h network/socket.h \
+processing/jobs/job.h \
+processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
+processing/jobs/callback_job.c processing/jobs/callback_job.h \
+processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
+processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
+processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
+processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
+processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
+processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
+processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
+processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
+processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
+processing/jobs/roam_job.c processing/jobs/roam_job.h \
+processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
+processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
+processing/scheduler.c processing/scheduler.h \
+processing/processor.c processing/processor.h \
+sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
+sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
+sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
+sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
+sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \
+sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
+sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
+sa/child_sa.c sa/child_sa.h \
+sa/ike_sa.c sa/ike_sa.h \
+sa/ike_sa_id.c sa/ike_sa_id.h \
+sa/ike_sa_manager.c sa/ike_sa_manager.h \
+sa/task_manager.c sa/task_manager.h \
+sa/keymat.c sa/keymat.h \
+sa/trap_manager.c sa/trap_manager.h \
+sa/tasks/child_create.c sa/tasks/child_create.h \
+sa/tasks/child_delete.c sa/tasks/child_delete.h \
+sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
+sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
+sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
+sa/tasks/ike_config.c sa/tasks/ike_config.h \
+sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
+sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
+sa/tasks/ike_init.c sa/tasks/ike_init.h \
+sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
+sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
+sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
+sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
+sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
+sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
+sa/tasks/task.c sa/tasks/task.h \
+credentials/credential_manager.c credentials/credential_manager.h \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
+credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
+credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+credentials/credential_set.h
+
+# adding the plugin source files
+
+LOCAL_SRC_FILES += $(call add_plugin, android)
+ifneq ($(call plugin_enabled, android)),)
+LOCAL_SHARED_LIBRARIES += libcutils
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, attr)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2)
+ifneq ($(call plugin_enabled, eap-aka-3gpp2)),)
+LOCAL_C_INCLUDES += $(libgmp_PATH)
+LOCAL_SHARED_LIBRARIES += libgmp
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-gtc)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-identity)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-md5)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-mschapv2)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-sim)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-pseudonym)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-reauth)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-sim-file)
+
+# adding libakasim if either eap-aka or eap-sim is enabled
+ifneq ($(or $(call plugin_enabled, eap-aka), $(call plugin_enabled, eap-sim)),)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libsimaka/
+LOCAL_SRC_FILES += $(addprefix ../libsimaka/, \
+ simaka_message.h simaka_message.c \
+ simaka_crypto.h simaka_crypto.c \
+ )
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink)
+
+LOCAL_SRC_FILES += $(call add_plugin, load-tester)
+
+LOCAL_SRC_FILES += $(call add_plugin, socket-default)
+
+LOCAL_SRC_FILES += $(call add_plugin, socket-dynamic)
+
+# build libcharon --------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/include \
+ $(strongswan_PATH)/src/libhydra \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libcharon
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
new file mode 100644
index 000000000..0eaccf7a0
--- /dev/null
+++ b/src/libcharon/Makefile.am
@@ -0,0 +1,418 @@
+lib_LTLIBRARIES = libcharon.la
+
+libcharon_la_SOURCES = \
+bus/bus.c bus/bus.h \
+bus/listeners/listener.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 config/peer_cfg.h \
+config/proposal.c config/proposal.h \
+config/auth_cfg.c config/auth_cfg.h \
+control/controller.c control/controller.h \
+daemon.c daemon.h \
+encoding/generator.c encoding/generator.h \
+encoding/message.c encoding/message.h \
+encoding/parser.c encoding/parser.h \
+encoding/payloads/auth_payload.c encoding/payloads/auth_payload.h \
+encoding/payloads/cert_payload.c encoding/payloads/cert_payload.h \
+encoding/payloads/certreq_payload.c encoding/payloads/certreq_payload.h \
+encoding/payloads/configuration_attribute.c encoding/payloads/configuration_attribute.h \
+encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
+encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
+encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
+encoding/payloads/encodings.c encoding/payloads/encodings.h \
+encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
+encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
+encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
+encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
+encoding/payloads/nonce_payload.c encoding/payloads/nonce_payload.h \
+encoding/payloads/notify_payload.c encoding/payloads/notify_payload.h \
+encoding/payloads/payload.c encoding/payloads/payload.h \
+encoding/payloads/proposal_substructure.c encoding/payloads/proposal_substructure.h \
+encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
+encoding/payloads/traffic_selector_substructure.c encoding/payloads/traffic_selector_substructure.h \
+encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
+encoding/payloads/transform_substructure.c encoding/payloads/transform_substructure.h \
+encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
+encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
+encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
+kernel/kernel_interface.c kernel/kernel_interface.h \
+kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+kernel/kernel_net.h \
+network/packet.c network/packet.h \
+network/receiver.c network/receiver.h \
+network/sender.c network/sender.h \
+network/socket_manager.c network/socket_manager.h network/socket.h \
+processing/jobs/job.h \
+processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
+processing/jobs/callback_job.c processing/jobs/callback_job.h \
+processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
+processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
+processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
+processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
+processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
+processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
+processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
+processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
+processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
+processing/jobs/roam_job.c processing/jobs/roam_job.h \
+processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
+processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
+processing/scheduler.c processing/scheduler.h \
+processing/processor.c processing/processor.h \
+sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
+sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
+sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
+sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
+sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \
+sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
+sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
+sa/child_sa.c sa/child_sa.h \
+sa/ike_sa.c sa/ike_sa.h \
+sa/ike_sa_id.c sa/ike_sa_id.h \
+sa/ike_sa_manager.c sa/ike_sa_manager.h \
+sa/task_manager.c sa/task_manager.h \
+sa/keymat.c sa/keymat.h \
+sa/trap_manager.c sa/trap_manager.h \
+sa/tasks/child_create.c sa/tasks/child_create.h \
+sa/tasks/child_delete.c sa/tasks/child_delete.h \
+sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
+sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
+sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
+sa/tasks/ike_config.c sa/tasks/ike_config.h \
+sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
+sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
+sa/tasks/ike_init.c sa/tasks/ike_init.h \
+sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
+sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
+sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
+sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
+sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
+sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
+sa/tasks/task.c sa/tasks/task.h \
+credentials/credential_manager.c credentials/credential_manager.h \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
+credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
+credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+credentials/credential_set.h
+
+daemon.lo : $(top_builddir)/config.status
+
+INCLUDES = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_PIDDIR=\"${piddir}\"
+
+libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB)
+
+EXTRA_DIST = Android.mk
+
+# compile options
+#################
+
+if USE_ME
+ libcharon_la_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
+ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
+ processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
+ sa/connect_manager.c sa/connect_manager.h \
+ sa/mediation_manager.c sa/mediation_manager.h \
+ sa/tasks/ike_me.c sa/tasks/ike_me.h
+endif
+
+if USE_CAPABILITIES
+ libcharon_la_LIBADD += -lcap
+endif
+
+# build optional plugins
+########################
+
+if MONOLITHIC
+SUBDIRS =
+else
+SUBDIRS = .
+endif
+
+PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins}
+
+if USE_LOAD_TESTER
+ SUBDIRS += plugins/load_tester
+ PLUGINS += load-tester
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/load_tester/libstrongswan-load-tester.la
+endif
+endif
+
+if USE_KERNEL_PFKEY
+ SUBDIRS += plugins/kernel_pfkey
+ PLUGINS += kernel-pfkey
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+endif
+endif
+
+if USE_KERNEL_PFROUTE
+ SUBDIRS += plugins/kernel_pfroute
+ PLUGINS += kernel-pfroute
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+endif
+endif
+
+if USE_KERNEL_KLIPS
+ SUBDIRS += plugins/kernel_klips
+ PLUGINS += kernel-klips
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/kernel_klips/libstrongswan-kernel-klips.la
+endif
+endif
+
+if USE_KERNEL_NETLINK
+ SUBDIRS += plugins/kernel_netlink
+ PLUGINS += kernel-netlink
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+endif
+endif
+
+if USE_SOCKET_DEFAULT
+ SUBDIRS += plugins/socket_default
+ PLUGINS += socket-default
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/socket_default/libstrongswan-socket-default.la
+endif
+endif
+
+if USE_SOCKET_RAW
+ SUBDIRS += plugins/socket_raw
+ PLUGINS += socket-raw
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/socket_raw/libstrongswan-socket-raw.la
+endif
+endif
+
+if USE_SOCKET_DYNAMIC
+ SUBDIRS += plugins/socket_dynamic
+ PLUGINS += socket-dynamic
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/socket_dynamic/libstrongswan-socket-dynamic.la
+endif
+endif
+
+if USE_FARP
+ SUBDIRS += plugins/farp
+ PLUGINS += farp
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/farp/libstrongswan-farp.la
+endif
+endif
+
+if USE_STROKE
+ SUBDIRS += plugins/stroke
+ PLUGINS += stroke
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/stroke/libstrongswan-stroke.la
+endif
+endif
+
+if USE_SMP
+ SUBDIRS += plugins/smp
+ PLUGINS += smp
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/smp/libstrongswan-smp.la
+endif
+endif
+
+if USE_SQL
+ SUBDIRS += plugins/sql
+ PLUGINS += sql
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/sql/libstrongswan-sql.la
+endif
+endif
+
+if USE_UPDOWN
+ SUBDIRS += plugins/updown
+ PLUGINS += updown
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/updown/libstrongswan-updown.la
+endif
+endif
+
+if USE_EAP_IDENTITY
+ SUBDIRS += plugins/eap_identity
+ PLUGINS += eap-identity
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_identity/libstrongswan-eap-identity.la
+endif
+endif
+
+if USE_EAP_SIM
+ SUBDIRS += plugins/eap_sim
+ PLUGINS += eap-sim
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_sim/libstrongswan-eap-sim.la
+endif
+endif
+
+if USE_EAP_SIM_FILE
+ SUBDIRS += plugins/eap_sim_file
+ PLUGINS += eap-sim-file
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+endif
+endif
+
+if USE_EAP_SIMAKA_PSEUDONYM
+ SUBDIRS += plugins/eap_simaka_pseudonym
+ PLUGINS += eap-simaka-pseudonym
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+endif
+endif
+
+if USE_EAP_SIMAKA_REAUTH
+ SUBDIRS += plugins/eap_simaka_reauth
+ PLUGINS += eap-simaka-reauth
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+endif
+endif
+
+if USE_EAP_AKA
+ SUBDIRS += plugins/eap_aka
+ PLUGINS += eap-aka
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_aka/libstrongswan-eap-aka.la
+endif
+endif
+
+if USE_EAP_AKA_3GPP2
+ SUBDIRS += plugins/eap_aka_3gpp2
+ PLUGINS += eap-aka-3gpp2
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+endif
+endif
+
+if USE_SIMAKA
+if MONOLITHIC
+ # otherwise this library is linked to both the eap_aka and the eap_sim plugin
+ libcharon_la_LIBADD += $(top_builddir)/src/libsimaka/libsimaka.la
+endif
+endif
+
+if USE_EAP_MD5
+ SUBDIRS += plugins/eap_md5
+ PLUGINS += eap-md5
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_md5/libstrongswan-eap-md5.la
+endif
+endif
+
+if USE_EAP_GTC
+ SUBDIRS += plugins/eap_gtc
+ PLUGINS += eap-gtc
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_gtc/libstrongswan-eap-gtc.la
+endif
+endif
+
+if USE_EAP_MSCHAPV2
+ SUBDIRS += plugins/eap_mschapv2
+ PLUGINS += eap-mschapv2
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+endif
+endif
+
+if USE_EAP_RADIUS
+ SUBDIRS += plugins/eap_radius
+ PLUGINS += eap-radius
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_radius/libstrongswan-eap-radius.la
+endif
+endif
+
+if USE_MEDSRV
+ SUBDIRS += plugins/medsrv
+ PLUGINS += medsrv
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/medsrv/libstrongswan-medsrv.la
+endif
+endif
+
+if USE_MEDCLI
+ SUBDIRS += plugins/medcli
+ PLUGINS += medcli
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/medcli/libstrongswan-medcli.la
+endif
+endif
+
+if USE_NM
+ SUBDIRS += plugins/nm
+ PLUGINS += nm
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/nm/libstrongswan-nm.la
+endif
+endif
+
+if USE_DHCP
+ SUBDIRS += plugins/dhcp
+ PLUGINS += dhcp
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/dhcp/libstrongswan-dhcp.la
+endif
+endif
+
+if USE_RESOLVE
+ SUBDIRS += plugins/resolve
+ PLUGINS += resolve
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/resolve/libstrongswan-resolve.la
+endif
+endif
+
+if USE_ANDROID
+ SUBDIRS += plugins/android
+ PLUGINS += android
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/android/libstrongswan-android.la
+endif
+endif
+
+if USE_HA
+ SUBDIRS += plugins/ha
+ PLUGINS += ha
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/ha/libstrongswan-ha.la
+endif
+endif
+
+if USE_UCI
+ SUBDIRS += plugins/uci
+ PLUGINS += uci
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/uci/libstrongswan-uci.la
+endif
+endif
+
+if USE_UNIT_TESTS
+ SUBDIRS += plugins/unit_tester
+ PLUGINS += unit-tester
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/unit_tester/libstrongswan-unit-tester.la
+endif
+endif
+
+AM_CFLAGS += -DPLUGINS=\""${PLUGINS}\""
+
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
new file mode 100644
index 000000000..0eb6f36f4
--- /dev/null
+++ b/src/libcharon/Makefile.in
@@ -0,0 +1,1994 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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@
+
+# compile options
+#################
+@USE_ME_TRUE@am__append_1 = 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/connect_manager.c sa/connect_manager.h \
+@USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \
+@USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h
+
+@USE_CAPABILITIES_TRUE@am__append_2 = -lcap
+@USE_LOAD_TESTER_TRUE@am__append_3 = plugins/load_tester
+@USE_LOAD_TESTER_TRUE@am__append_4 = load-tester
+@MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE@am__append_5 = plugins/load_tester/libstrongswan-load-tester.la
+@USE_KERNEL_PFKEY_TRUE@am__append_6 = plugins/kernel_pfkey
+@USE_KERNEL_PFKEY_TRUE@am__append_7 = kernel-pfkey
+@MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE@am__append_8 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+@USE_KERNEL_PFROUTE_TRUE@am__append_9 = plugins/kernel_pfroute
+@USE_KERNEL_PFROUTE_TRUE@am__append_10 = kernel-pfroute
+@MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE@am__append_11 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+@USE_KERNEL_KLIPS_TRUE@am__append_12 = plugins/kernel_klips
+@USE_KERNEL_KLIPS_TRUE@am__append_13 = kernel-klips
+@MONOLITHIC_TRUE@@USE_KERNEL_KLIPS_TRUE@am__append_14 = plugins/kernel_klips/libstrongswan-kernel-klips.la
+@USE_KERNEL_NETLINK_TRUE@am__append_15 = plugins/kernel_netlink
+@USE_KERNEL_NETLINK_TRUE@am__append_16 = kernel-netlink
+@MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE@am__append_17 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+@USE_SOCKET_DEFAULT_TRUE@am__append_18 = plugins/socket_default
+@USE_SOCKET_DEFAULT_TRUE@am__append_19 = socket-default
+@MONOLITHIC_TRUE@@USE_SOCKET_DEFAULT_TRUE@am__append_20 = plugins/socket_default/libstrongswan-socket-default.la
+@USE_SOCKET_RAW_TRUE@am__append_21 = plugins/socket_raw
+@USE_SOCKET_RAW_TRUE@am__append_22 = socket-raw
+@MONOLITHIC_TRUE@@USE_SOCKET_RAW_TRUE@am__append_23 = plugins/socket_raw/libstrongswan-socket-raw.la
+@USE_SOCKET_DYNAMIC_TRUE@am__append_24 = plugins/socket_dynamic
+@USE_SOCKET_DYNAMIC_TRUE@am__append_25 = socket-dynamic
+@MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE@am__append_26 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la
+@USE_FARP_TRUE@am__append_27 = plugins/farp
+@USE_FARP_TRUE@am__append_28 = farp
+@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_29 = plugins/farp/libstrongswan-farp.la
+@USE_STROKE_TRUE@am__append_30 = plugins/stroke
+@USE_STROKE_TRUE@am__append_31 = stroke
+@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_32 = plugins/stroke/libstrongswan-stroke.la
+@USE_SMP_TRUE@am__append_33 = plugins/smp
+@USE_SMP_TRUE@am__append_34 = smp
+@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_35 = plugins/smp/libstrongswan-smp.la
+@USE_SQL_TRUE@am__append_36 = plugins/sql
+@USE_SQL_TRUE@am__append_37 = sql
+@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_38 = plugins/sql/libstrongswan-sql.la
+@USE_UPDOWN_TRUE@am__append_39 = plugins/updown
+@USE_UPDOWN_TRUE@am__append_40 = updown
+@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_41 = plugins/updown/libstrongswan-updown.la
+@USE_EAP_IDENTITY_TRUE@am__append_42 = plugins/eap_identity
+@USE_EAP_IDENTITY_TRUE@am__append_43 = eap-identity
+@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_44 = plugins/eap_identity/libstrongswan-eap-identity.la
+@USE_EAP_SIM_TRUE@am__append_45 = plugins/eap_sim
+@USE_EAP_SIM_TRUE@am__append_46 = eap-sim
+@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_47 = plugins/eap_sim/libstrongswan-eap-sim.la
+@USE_EAP_SIM_FILE_TRUE@am__append_48 = plugins/eap_sim_file
+@USE_EAP_SIM_FILE_TRUE@am__append_49 = eap-sim-file
+@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_50 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_51 = plugins/eap_simaka_pseudonym
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_52 = eap-simaka-pseudonym
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_53 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_54 = plugins/eap_simaka_reauth
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_55 = eap-simaka-reauth
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_56 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+@USE_EAP_AKA_TRUE@am__append_57 = plugins/eap_aka
+@USE_EAP_AKA_TRUE@am__append_58 = eap-aka
+@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_59 = plugins/eap_aka/libstrongswan-eap-aka.la
+@USE_EAP_AKA_3GPP2_TRUE@am__append_60 = plugins/eap_aka_3gpp2
+@USE_EAP_AKA_3GPP2_TRUE@am__append_61 = eap-aka-3gpp2
+@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_62 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_63 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_EAP_MD5_TRUE@am__append_64 = plugins/eap_md5
+@USE_EAP_MD5_TRUE@am__append_65 = eap-md5
+@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_66 = plugins/eap_md5/libstrongswan-eap-md5.la
+@USE_EAP_GTC_TRUE@am__append_67 = plugins/eap_gtc
+@USE_EAP_GTC_TRUE@am__append_68 = eap-gtc
+@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_69 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+@USE_EAP_MSCHAPV2_TRUE@am__append_70 = plugins/eap_mschapv2
+@USE_EAP_MSCHAPV2_TRUE@am__append_71 = eap-mschapv2
+@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_72 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+@USE_EAP_RADIUS_TRUE@am__append_73 = plugins/eap_radius
+@USE_EAP_RADIUS_TRUE@am__append_74 = eap-radius
+@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_75 = plugins/eap_radius/libstrongswan-eap-radius.la
+@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv
+@USE_MEDSRV_TRUE@am__append_77 = medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_78 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli
+@USE_MEDCLI_TRUE@am__append_80 = medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_81 = plugins/medcli/libstrongswan-medcli.la
+@USE_NM_TRUE@am__append_82 = plugins/nm
+@USE_NM_TRUE@am__append_83 = nm
+@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_84 = plugins/nm/libstrongswan-nm.la
+@USE_DHCP_TRUE@am__append_85 = plugins/dhcp
+@USE_DHCP_TRUE@am__append_86 = dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_87 = plugins/dhcp/libstrongswan-dhcp.la
+@USE_RESOLVE_TRUE@am__append_88 = plugins/resolve
+@USE_RESOLVE_TRUE@am__append_89 = resolve
+@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_90 = plugins/resolve/libstrongswan-resolve.la
+@USE_ANDROID_TRUE@am__append_91 = plugins/android
+@USE_ANDROID_TRUE@am__append_92 = android
+@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_93 = plugins/android/libstrongswan-android.la
+@USE_HA_TRUE@am__append_94 = plugins/ha
+@USE_HA_TRUE@am__append_95 = ha
+@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_96 = plugins/ha/libstrongswan-ha.la
+@USE_UCI_TRUE@am__append_97 = plugins/uci
+@USE_UCI_TRUE@am__append_98 = uci
+@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_99 = plugins/uci/libstrongswan-uci.la
+@USE_UNIT_TESTS_TRUE@am__append_100 = plugins/unit_tester
+@USE_UNIT_TESTS_TRUE@am__append_101 = unit-tester
+@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_102 = plugins/unit_tester/libstrongswan-unit-tester.la
+subdir = src/libcharon
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__append_5) $(am__append_8) \
+ $(am__append_11) $(am__append_14) $(am__append_17) \
+ $(am__append_20) $(am__append_23) $(am__append_26) \
+ $(am__append_29) $(am__append_32) $(am__append_35) \
+ $(am__append_38) $(am__append_41) $(am__append_44) \
+ $(am__append_47) $(am__append_50) $(am__append_53) \
+ $(am__append_56) $(am__append_59) $(am__append_62) \
+ $(am__append_63) $(am__append_66) $(am__append_69) \
+ $(am__append_72) $(am__append_75) $(am__append_78) \
+ $(am__append_81) $(am__append_84) $(am__append_87) \
+ $(am__append_90) $(am__append_93) $(am__append_96) \
+ $(am__append_99) $(am__append_102)
+am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
+ bus/listeners/listener.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 config/peer_cfg.h config/proposal.c \
+ config/proposal.h config/auth_cfg.c config/auth_cfg.h \
+ control/controller.c control/controller.h daemon.c daemon.h \
+ encoding/generator.c encoding/generator.h encoding/message.c \
+ encoding/message.h encoding/parser.c encoding/parser.h \
+ encoding/payloads/auth_payload.c \
+ encoding/payloads/auth_payload.h \
+ encoding/payloads/cert_payload.c \
+ encoding/payloads/cert_payload.h \
+ encoding/payloads/certreq_payload.c \
+ encoding/payloads/certreq_payload.h \
+ encoding/payloads/configuration_attribute.c \
+ encoding/payloads/configuration_attribute.h \
+ encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
+ encoding/payloads/delete_payload.c \
+ encoding/payloads/delete_payload.h \
+ encoding/payloads/eap_payload.c \
+ encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
+ encoding/payloads/encodings.h \
+ encoding/payloads/encryption_payload.c \
+ encoding/payloads/encryption_payload.h \
+ encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
+ encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
+ encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
+ encoding/payloads/nonce_payload.c \
+ encoding/payloads/nonce_payload.h \
+ encoding/payloads/notify_payload.c \
+ encoding/payloads/notify_payload.h encoding/payloads/payload.c \
+ encoding/payloads/payload.h \
+ encoding/payloads/proposal_substructure.c \
+ encoding/payloads/proposal_substructure.h \
+ encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
+ encoding/payloads/traffic_selector_substructure.c \
+ encoding/payloads/traffic_selector_substructure.h \
+ encoding/payloads/transform_attribute.c \
+ encoding/payloads/transform_attribute.h \
+ encoding/payloads/transform_substructure.c \
+ encoding/payloads/transform_substructure.h \
+ encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
+ encoding/payloads/unknown_payload.c \
+ encoding/payloads/unknown_payload.h \
+ encoding/payloads/vendor_id_payload.c \
+ encoding/payloads/vendor_id_payload.h \
+ kernel/kernel_interface.c kernel/kernel_interface.h \
+ kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+ kernel/kernel_net.h network/packet.c network/packet.h \
+ network/receiver.c network/receiver.h network/sender.c \
+ network/sender.h network/socket_manager.c \
+ network/socket_manager.h network/socket.h \
+ processing/jobs/job.h processing/jobs/acquire_job.c \
+ processing/jobs/acquire_job.h processing/jobs/callback_job.c \
+ processing/jobs/callback_job.h \
+ processing/jobs/delete_child_sa_job.c \
+ processing/jobs/delete_child_sa_job.h \
+ processing/jobs/delete_ike_sa_job.c \
+ processing/jobs/delete_ike_sa_job.h \
+ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
+ processing/jobs/process_message_job.c \
+ processing/jobs/process_message_job.h \
+ processing/jobs/rekey_child_sa_job.c \
+ processing/jobs/rekey_child_sa_job.h \
+ processing/jobs/rekey_ike_sa_job.c \
+ processing/jobs/rekey_ike_sa_job.h \
+ processing/jobs/retransmit_job.c \
+ processing/jobs/retransmit_job.h \
+ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
+ processing/jobs/send_keepalive_job.c \
+ processing/jobs/send_keepalive_job.h \
+ processing/jobs/roam_job.c processing/jobs/roam_job.h \
+ processing/jobs/update_sa_job.c \
+ processing/jobs/update_sa_job.h \
+ processing/jobs/inactivity_job.c \
+ processing/jobs/inactivity_job.h processing/scheduler.c \
+ processing/scheduler.h processing/processor.c \
+ processing/processor.h sa/authenticators/authenticator.c \
+ sa/authenticators/authenticator.h \
+ sa/authenticators/eap_authenticator.c \
+ sa/authenticators/eap_authenticator.h \
+ sa/authenticators/eap/eap_method.c \
+ sa/authenticators/eap/eap_method.h \
+ sa/authenticators/eap/eap_manager.c \
+ sa/authenticators/eap/eap_manager.h \
+ sa/authenticators/eap/sim_manager.c \
+ sa/authenticators/eap/sim_manager.h \
+ sa/authenticators/psk_authenticator.c \
+ sa/authenticators/psk_authenticator.h \
+ sa/authenticators/pubkey_authenticator.c \
+ sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
+ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
+ sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
+ sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/trap_manager.c sa/trap_manager.h sa/tasks/child_create.c \
+ sa/tasks/child_create.h sa/tasks/child_delete.c \
+ sa/tasks/child_delete.h sa/tasks/child_rekey.c \
+ sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+ sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
+ sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
+ sa/tasks/ike_config.c sa/tasks/ike_config.h \
+ sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
+ sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
+ sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
+ sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
+ sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
+ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
+ sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
+ sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
+ credentials/credential_manager.c \
+ credentials/credential_manager.h \
+ credentials/sets/auth_cfg_wrapper.c \
+ credentials/sets/auth_cfg_wrapper.h \
+ credentials/sets/ocsp_response_wrapper.c \
+ credentials/sets/ocsp_response_wrapper.h \
+ credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+ credentials/credential_set.h \
+ encoding/payloads/endpoint_notify.c \
+ encoding/payloads/endpoint_notify.h \
+ processing/jobs/initiate_mediation_job.c \
+ processing/jobs/initiate_mediation_job.h \
+ processing/jobs/mediation_job.c \
+ processing/jobs/mediation_job.h sa/connect_manager.c \
+ sa/connect_manager.h sa/mediation_manager.c \
+ sa/mediation_manager.h sa/tasks/ike_me.c sa/tasks/ike_me.h
+@USE_ME_TRUE@am__objects_1 = endpoint_notify.lo \
+@USE_ME_TRUE@ initiate_mediation_job.lo mediation_job.lo \
+@USE_ME_TRUE@ connect_manager.lo mediation_manager.lo ike_me.lo
+am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \
+ backend_manager.lo child_cfg.lo ike_cfg.lo peer_cfg.lo \
+ proposal.lo auth_cfg.lo controller.lo daemon.lo generator.lo \
+ message.lo parser.lo auth_payload.lo cert_payload.lo \
+ certreq_payload.lo configuration_attribute.lo cp_payload.lo \
+ delete_payload.lo eap_payload.lo encodings.lo \
+ encryption_payload.lo id_payload.lo ike_header.lo \
+ ke_payload.lo nonce_payload.lo notify_payload.lo payload.lo \
+ proposal_substructure.lo sa_payload.lo \
+ traffic_selector_substructure.lo transform_attribute.lo \
+ transform_substructure.lo ts_payload.lo unknown_payload.lo \
+ vendor_id_payload.lo kernel_interface.lo kernel_ipsec.lo \
+ packet.lo receiver.lo sender.lo socket_manager.lo \
+ acquire_job.lo callback_job.lo delete_child_sa_job.lo \
+ delete_ike_sa_job.lo migrate_job.lo process_message_job.lo \
+ rekey_child_sa_job.lo rekey_ike_sa_job.lo retransmit_job.lo \
+ send_dpd_job.lo send_keepalive_job.lo roam_job.lo \
+ update_sa_job.lo inactivity_job.lo scheduler.lo processor.lo \
+ authenticator.lo eap_authenticator.lo eap_method.lo \
+ eap_manager.lo sim_manager.lo psk_authenticator.lo \
+ pubkey_authenticator.lo child_sa.lo ike_sa.lo ike_sa_id.lo \
+ ike_sa_manager.lo task_manager.lo keymat.lo trap_manager.lo \
+ child_create.lo child_delete.lo child_rekey.lo ike_auth.lo \
+ ike_cert_pre.lo ike_cert_post.lo ike_config.lo ike_delete.lo \
+ ike_dpd.lo ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \
+ ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \
+ credential_manager.lo auth_cfg_wrapper.lo \
+ ocsp_response_wrapper.lo cert_cache.lo $(am__objects_1)
+libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libcharon_la_SOURCES)
+DIST_SOURCES = $(am__libcharon_la_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = . plugins/load_tester plugins/kernel_pfkey \
+ plugins/kernel_pfroute plugins/kernel_klips \
+ plugins/kernel_netlink plugins/socket_default \
+ plugins/socket_raw plugins/socket_dynamic plugins/farp \
+ plugins/stroke plugins/smp plugins/sql plugins/updown \
+ plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \
+ plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
+ plugins/eap_aka plugins/eap_aka_3gpp2 plugins/eap_md5 \
+ plugins/eap_gtc plugins/eap_mschapv2 plugins/eap_radius \
+ plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \
+ plugins/resolve plugins/android plugins/ha plugins/uci \
+ plugins/unit_tester
+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@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+lib_LTLIBRARIES = libcharon.la
+libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.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 \
+ config/peer_cfg.h config/proposal.c config/proposal.h \
+ config/auth_cfg.c config/auth_cfg.h control/controller.c \
+ control/controller.h daemon.c daemon.h encoding/generator.c \
+ encoding/generator.h encoding/message.c encoding/message.h \
+ encoding/parser.c encoding/parser.h \
+ encoding/payloads/auth_payload.c \
+ encoding/payloads/auth_payload.h \
+ encoding/payloads/cert_payload.c \
+ encoding/payloads/cert_payload.h \
+ encoding/payloads/certreq_payload.c \
+ encoding/payloads/certreq_payload.h \
+ encoding/payloads/configuration_attribute.c \
+ encoding/payloads/configuration_attribute.h \
+ encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
+ encoding/payloads/delete_payload.c \
+ encoding/payloads/delete_payload.h \
+ encoding/payloads/eap_payload.c \
+ encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
+ encoding/payloads/encodings.h \
+ encoding/payloads/encryption_payload.c \
+ encoding/payloads/encryption_payload.h \
+ encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
+ encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
+ encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
+ encoding/payloads/nonce_payload.c \
+ encoding/payloads/nonce_payload.h \
+ encoding/payloads/notify_payload.c \
+ encoding/payloads/notify_payload.h encoding/payloads/payload.c \
+ encoding/payloads/payload.h \
+ encoding/payloads/proposal_substructure.c \
+ encoding/payloads/proposal_substructure.h \
+ encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
+ encoding/payloads/traffic_selector_substructure.c \
+ encoding/payloads/traffic_selector_substructure.h \
+ encoding/payloads/transform_attribute.c \
+ encoding/payloads/transform_attribute.h \
+ encoding/payloads/transform_substructure.c \
+ encoding/payloads/transform_substructure.h \
+ encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
+ encoding/payloads/unknown_payload.c \
+ encoding/payloads/unknown_payload.h \
+ encoding/payloads/vendor_id_payload.c \
+ encoding/payloads/vendor_id_payload.h \
+ kernel/kernel_interface.c kernel/kernel_interface.h \
+ kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+ kernel/kernel_net.h network/packet.c network/packet.h \
+ network/receiver.c network/receiver.h network/sender.c \
+ network/sender.h network/socket_manager.c \
+ network/socket_manager.h network/socket.h \
+ processing/jobs/job.h processing/jobs/acquire_job.c \
+ processing/jobs/acquire_job.h processing/jobs/callback_job.c \
+ processing/jobs/callback_job.h \
+ processing/jobs/delete_child_sa_job.c \
+ processing/jobs/delete_child_sa_job.h \
+ processing/jobs/delete_ike_sa_job.c \
+ processing/jobs/delete_ike_sa_job.h \
+ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
+ processing/jobs/process_message_job.c \
+ processing/jobs/process_message_job.h \
+ processing/jobs/rekey_child_sa_job.c \
+ processing/jobs/rekey_child_sa_job.h \
+ processing/jobs/rekey_ike_sa_job.c \
+ processing/jobs/rekey_ike_sa_job.h \
+ processing/jobs/retransmit_job.c \
+ processing/jobs/retransmit_job.h \
+ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
+ processing/jobs/send_keepalive_job.c \
+ processing/jobs/send_keepalive_job.h \
+ processing/jobs/roam_job.c processing/jobs/roam_job.h \
+ processing/jobs/update_sa_job.c \
+ processing/jobs/update_sa_job.h \
+ processing/jobs/inactivity_job.c \
+ processing/jobs/inactivity_job.h processing/scheduler.c \
+ processing/scheduler.h processing/processor.c \
+ processing/processor.h sa/authenticators/authenticator.c \
+ sa/authenticators/authenticator.h \
+ sa/authenticators/eap_authenticator.c \
+ sa/authenticators/eap_authenticator.h \
+ sa/authenticators/eap/eap_method.c \
+ sa/authenticators/eap/eap_method.h \
+ sa/authenticators/eap/eap_manager.c \
+ sa/authenticators/eap/eap_manager.h \
+ sa/authenticators/eap/sim_manager.c \
+ sa/authenticators/eap/sim_manager.h \
+ sa/authenticators/psk_authenticator.c \
+ sa/authenticators/psk_authenticator.h \
+ sa/authenticators/pubkey_authenticator.c \
+ sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
+ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
+ sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
+ sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/trap_manager.c sa/trap_manager.h sa/tasks/child_create.c \
+ sa/tasks/child_create.h sa/tasks/child_delete.c \
+ sa/tasks/child_delete.h sa/tasks/child_rekey.c \
+ sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+ sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
+ sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
+ sa/tasks/ike_config.c sa/tasks/ike_config.h \
+ sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
+ sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
+ sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
+ sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
+ sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
+ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
+ sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
+ sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
+ credentials/credential_manager.c \
+ credentials/credential_manager.h \
+ credentials/sets/auth_cfg_wrapper.c \
+ credentials/sets/auth_cfg_wrapper.h \
+ credentials/sets/ocsp_response_wrapper.c \
+ credentials/sets/ocsp_response_wrapper.h \
+ credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+ credentials/credential_set.h $(am__append_1)
+INCLUDES = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DPLUGINS=\""${PLUGINS}\""
+libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \
+ $(am__append_2) $(am__append_5) $(am__append_8) \
+ $(am__append_11) $(am__append_14) $(am__append_17) \
+ $(am__append_20) $(am__append_23) $(am__append_26) \
+ $(am__append_29) $(am__append_32) $(am__append_35) \
+ $(am__append_38) $(am__append_41) $(am__append_44) \
+ $(am__append_47) $(am__append_50) $(am__append_53) \
+ $(am__append_56) $(am__append_59) $(am__append_62) \
+ $(am__append_63) $(am__append_66) $(am__append_69) \
+ $(am__append_72) $(am__append_75) $(am__append_78) \
+ $(am__append_81) $(am__append_84) $(am__append_87) \
+ $(am__append_90) $(am__append_93) $(am__append_96) \
+ $(am__append_99) $(am__append_102)
+EXTRA_DIST = Android.mk
+@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_6) \
+@MONOLITHIC_FALSE@ $(am__append_9) $(am__append_12) \
+@MONOLITHIC_FALSE@ $(am__append_15) $(am__append_18) \
+@MONOLITHIC_FALSE@ $(am__append_21) $(am__append_24) \
+@MONOLITHIC_FALSE@ $(am__append_27) $(am__append_30) \
+@MONOLITHIC_FALSE@ $(am__append_33) $(am__append_36) \
+@MONOLITHIC_FALSE@ $(am__append_39) $(am__append_42) \
+@MONOLITHIC_FALSE@ $(am__append_45) $(am__append_48) \
+@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_54) \
+@MONOLITHIC_FALSE@ $(am__append_57) $(am__append_60) \
+@MONOLITHIC_FALSE@ $(am__append_64) $(am__append_67) \
+@MONOLITHIC_FALSE@ $(am__append_70) $(am__append_73) \
+@MONOLITHIC_FALSE@ $(am__append_76) $(am__append_79) \
+@MONOLITHIC_FALSE@ $(am__append_82) $(am__append_85) \
+@MONOLITHIC_FALSE@ $(am__append_88) $(am__append_91) \
+@MONOLITHIC_FALSE@ $(am__append_94) $(am__append_97) \
+@MONOLITHIC_FALSE@ $(am__append_100)
+
+# build optional plugins
+########################
+@MONOLITHIC_TRUE@SUBDIRS = $(am__append_3) $(am__append_6) \
+@MONOLITHIC_TRUE@ $(am__append_9) $(am__append_12) \
+@MONOLITHIC_TRUE@ $(am__append_15) $(am__append_18) \
+@MONOLITHIC_TRUE@ $(am__append_21) $(am__append_24) \
+@MONOLITHIC_TRUE@ $(am__append_27) $(am__append_30) \
+@MONOLITHIC_TRUE@ $(am__append_33) $(am__append_36) \
+@MONOLITHIC_TRUE@ $(am__append_39) $(am__append_42) \
+@MONOLITHIC_TRUE@ $(am__append_45) $(am__append_48) \
+@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_54) \
+@MONOLITHIC_TRUE@ $(am__append_57) $(am__append_60) \
+@MONOLITHIC_TRUE@ $(am__append_64) $(am__append_67) \
+@MONOLITHIC_TRUE@ $(am__append_70) $(am__append_73) \
+@MONOLITHIC_TRUE@ $(am__append_76) $(am__append_79) \
+@MONOLITHIC_TRUE@ $(am__append_82) $(am__append_85) \
+@MONOLITHIC_TRUE@ $(am__append_88) $(am__append_91) \
+@MONOLITHIC_TRUE@ $(am__append_94) $(am__append_97) \
+@MONOLITHIC_TRUE@ $(am__append_100)
+PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins} $(am__append_4) \
+ $(am__append_7) $(am__append_10) $(am__append_13) \
+ $(am__append_16) $(am__append_19) $(am__append_22) \
+ $(am__append_25) $(am__append_28) $(am__append_31) \
+ $(am__append_34) $(am__append_37) $(am__append_40) \
+ $(am__append_43) $(am__append_46) $(am__append_49) \
+ $(am__append_52) $(am__append_55) $(am__append_58) \
+ $(am__append_61) $(am__append_65) $(am__append_68) \
+ $(am__append_71) $(am__append_74) $(am__append_77) \
+ $(am__append_80) $(am__append_83) $(am__append_86) \
+ $(am__append_89) $(am__append_92) $(am__append_95) \
+ $(am__append_98) $(am__append_101)
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/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-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libcharon.la: $(libcharon_la_OBJECTS) $(libcharon_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libcharon_la_OBJECTS) $(libcharon_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg_wrapper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certreq_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_create.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_rekey.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_sa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_method.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryption_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/endpoint_notify.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_logger.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/id_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth_lifetime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_post.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_pre.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_dpd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_header.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_init.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_me.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_mobike.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_natd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_reauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_rekey.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_id.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_vendor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inactivity_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_message_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_substructure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_child_sa_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_ike_sa_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retransmit_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roam_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sa_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_dpd_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_keepalive_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_logger.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector_substructure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_substructure.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trap_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ts_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unknown_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update_sa_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor_id_payload.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+bus.lo: bus/bus.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bus.lo -MD -MP -MF $(DEPDIR)/bus.Tpo -c -o bus.lo `test -f 'bus/bus.c' || echo '$(srcdir)/'`bus/bus.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bus.Tpo $(DEPDIR)/bus.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/bus.c' object='bus.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bus.lo `test -f 'bus/bus.c' || echo '$(srcdir)/'`bus/bus.c
+
+file_logger.lo: bus/listeners/file_logger.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_logger.lo -MD -MP -MF $(DEPDIR)/file_logger.Tpo -c -o file_logger.lo `test -f 'bus/listeners/file_logger.c' || echo '$(srcdir)/'`bus/listeners/file_logger.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/file_logger.Tpo $(DEPDIR)/file_logger.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/file_logger.c' object='file_logger.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_logger.lo `test -f 'bus/listeners/file_logger.c' || echo '$(srcdir)/'`bus/listeners/file_logger.c
+
+sys_logger.lo: bus/listeners/sys_logger.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sys_logger.lo -MD -MP -MF $(DEPDIR)/sys_logger.Tpo -c -o sys_logger.lo `test -f 'bus/listeners/sys_logger.c' || echo '$(srcdir)/'`bus/listeners/sys_logger.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sys_logger.Tpo $(DEPDIR)/sys_logger.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bus/listeners/sys_logger.c' object='sys_logger.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sys_logger.lo `test -f 'bus/listeners/sys_logger.c' || echo '$(srcdir)/'`bus/listeners/sys_logger.c
+
+backend_manager.lo: config/backend_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_manager.lo -MD -MP -MF $(DEPDIR)/backend_manager.Tpo -c -o backend_manager.lo `test -f 'config/backend_manager.c' || echo '$(srcdir)/'`config/backend_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/backend_manager.Tpo $(DEPDIR)/backend_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/backend_manager.c' object='backend_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_manager.lo `test -f 'config/backend_manager.c' || echo '$(srcdir)/'`config/backend_manager.c
+
+child_cfg.lo: config/child_cfg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_cfg.lo -MD -MP -MF $(DEPDIR)/child_cfg.Tpo -c -o child_cfg.lo `test -f 'config/child_cfg.c' || echo '$(srcdir)/'`config/child_cfg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_cfg.Tpo $(DEPDIR)/child_cfg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/child_cfg.c' object='child_cfg.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_cfg.lo `test -f 'config/child_cfg.c' || echo '$(srcdir)/'`config/child_cfg.c
+
+ike_cfg.lo: config/ike_cfg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cfg.lo -MD -MP -MF $(DEPDIR)/ike_cfg.Tpo -c -o ike_cfg.lo `test -f 'config/ike_cfg.c' || echo '$(srcdir)/'`config/ike_cfg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cfg.Tpo $(DEPDIR)/ike_cfg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/ike_cfg.c' object='ike_cfg.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cfg.lo `test -f 'config/ike_cfg.c' || echo '$(srcdir)/'`config/ike_cfg.c
+
+peer_cfg.lo: config/peer_cfg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT peer_cfg.lo -MD -MP -MF $(DEPDIR)/peer_cfg.Tpo -c -o peer_cfg.lo `test -f 'config/peer_cfg.c' || echo '$(srcdir)/'`config/peer_cfg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/peer_cfg.Tpo $(DEPDIR)/peer_cfg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/peer_cfg.c' object='peer_cfg.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o peer_cfg.lo `test -f 'config/peer_cfg.c' || echo '$(srcdir)/'`config/peer_cfg.c
+
+proposal.lo: config/proposal.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal.lo -MD -MP -MF $(DEPDIR)/proposal.Tpo -c -o proposal.lo `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal.Tpo $(DEPDIR)/proposal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/proposal.c' object='proposal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal.lo `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c
+
+auth_cfg.lo: config/auth_cfg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.lo -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/auth_cfg.c' object='auth_cfg.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
+
+controller.lo: control/controller.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.lo -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.lo `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/controller.c' object='controller.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o controller.lo `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c
+
+generator.lo: encoding/generator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT generator.lo -MD -MP -MF $(DEPDIR)/generator.Tpo -c -o generator.lo `test -f 'encoding/generator.c' || echo '$(srcdir)/'`encoding/generator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generator.Tpo $(DEPDIR)/generator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/generator.c' object='generator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o generator.lo `test -f 'encoding/generator.c' || echo '$(srcdir)/'`encoding/generator.c
+
+message.lo: encoding/message.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT message.lo -MD -MP -MF $(DEPDIR)/message.Tpo -c -o message.lo `test -f 'encoding/message.c' || echo '$(srcdir)/'`encoding/message.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/message.Tpo $(DEPDIR)/message.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/message.c' object='message.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o message.lo `test -f 'encoding/message.c' || echo '$(srcdir)/'`encoding/message.c
+
+parser.lo: encoding/parser.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser.lo -MD -MP -MF $(DEPDIR)/parser.Tpo -c -o parser.lo `test -f 'encoding/parser.c' || echo '$(srcdir)/'`encoding/parser.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser.Tpo $(DEPDIR)/parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/parser.c' object='parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser.lo `test -f 'encoding/parser.c' || echo '$(srcdir)/'`encoding/parser.c
+
+auth_payload.lo: encoding/payloads/auth_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_payload.lo -MD -MP -MF $(DEPDIR)/auth_payload.Tpo -c -o auth_payload.lo `test -f 'encoding/payloads/auth_payload.c' || echo '$(srcdir)/'`encoding/payloads/auth_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_payload.Tpo $(DEPDIR)/auth_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/auth_payload.c' object='auth_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_payload.lo `test -f 'encoding/payloads/auth_payload.c' || echo '$(srcdir)/'`encoding/payloads/auth_payload.c
+
+cert_payload.lo: encoding/payloads/cert_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_payload.lo -MD -MP -MF $(DEPDIR)/cert_payload.Tpo -c -o cert_payload.lo `test -f 'encoding/payloads/cert_payload.c' || echo '$(srcdir)/'`encoding/payloads/cert_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_payload.Tpo $(DEPDIR)/cert_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cert_payload.c' object='cert_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_payload.lo `test -f 'encoding/payloads/cert_payload.c' || echo '$(srcdir)/'`encoding/payloads/cert_payload.c
+
+certreq_payload.lo: encoding/payloads/certreq_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT certreq_payload.lo -MD -MP -MF $(DEPDIR)/certreq_payload.Tpo -c -o certreq_payload.lo `test -f 'encoding/payloads/certreq_payload.c' || echo '$(srcdir)/'`encoding/payloads/certreq_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/certreq_payload.Tpo $(DEPDIR)/certreq_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/certreq_payload.c' object='certreq_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o certreq_payload.lo `test -f 'encoding/payloads/certreq_payload.c' || echo '$(srcdir)/'`encoding/payloads/certreq_payload.c
+
+configuration_attribute.lo: encoding/payloads/configuration_attribute.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT configuration_attribute.lo -MD -MP -MF $(DEPDIR)/configuration_attribute.Tpo -c -o configuration_attribute.lo `test -f 'encoding/payloads/configuration_attribute.c' || echo '$(srcdir)/'`encoding/payloads/configuration_attribute.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/configuration_attribute.Tpo $(DEPDIR)/configuration_attribute.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/configuration_attribute.c' object='configuration_attribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o configuration_attribute.lo `test -f 'encoding/payloads/configuration_attribute.c' || echo '$(srcdir)/'`encoding/payloads/configuration_attribute.c
+
+cp_payload.lo: encoding/payloads/cp_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cp_payload.lo -MD -MP -MF $(DEPDIR)/cp_payload.Tpo -c -o cp_payload.lo `test -f 'encoding/payloads/cp_payload.c' || echo '$(srcdir)/'`encoding/payloads/cp_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cp_payload.Tpo $(DEPDIR)/cp_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/cp_payload.c' object='cp_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cp_payload.lo `test -f 'encoding/payloads/cp_payload.c' || echo '$(srcdir)/'`encoding/payloads/cp_payload.c
+
+delete_payload.lo: encoding/payloads/delete_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_payload.lo -MD -MP -MF $(DEPDIR)/delete_payload.Tpo -c -o delete_payload.lo `test -f 'encoding/payloads/delete_payload.c' || echo '$(srcdir)/'`encoding/payloads/delete_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_payload.Tpo $(DEPDIR)/delete_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/delete_payload.c' object='delete_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_payload.lo `test -f 'encoding/payloads/delete_payload.c' || echo '$(srcdir)/'`encoding/payloads/delete_payload.c
+
+eap_payload.lo: encoding/payloads/eap_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_payload.lo -MD -MP -MF $(DEPDIR)/eap_payload.Tpo -c -o eap_payload.lo `test -f 'encoding/payloads/eap_payload.c' || echo '$(srcdir)/'`encoding/payloads/eap_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_payload.Tpo $(DEPDIR)/eap_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/eap_payload.c' object='eap_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_payload.lo `test -f 'encoding/payloads/eap_payload.c' || echo '$(srcdir)/'`encoding/payloads/eap_payload.c
+
+encodings.lo: encoding/payloads/encodings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encodings.lo -MD -MP -MF $(DEPDIR)/encodings.Tpo -c -o encodings.lo `test -f 'encoding/payloads/encodings.c' || echo '$(srcdir)/'`encoding/payloads/encodings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encodings.Tpo $(DEPDIR)/encodings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encodings.c' object='encodings.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encodings.lo `test -f 'encoding/payloads/encodings.c' || echo '$(srcdir)/'`encoding/payloads/encodings.c
+
+encryption_payload.lo: encoding/payloads/encryption_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encryption_payload.lo -MD -MP -MF $(DEPDIR)/encryption_payload.Tpo -c -o encryption_payload.lo `test -f 'encoding/payloads/encryption_payload.c' || echo '$(srcdir)/'`encoding/payloads/encryption_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/encryption_payload.Tpo $(DEPDIR)/encryption_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/encryption_payload.c' object='encryption_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encryption_payload.lo `test -f 'encoding/payloads/encryption_payload.c' || echo '$(srcdir)/'`encoding/payloads/encryption_payload.c
+
+id_payload.lo: encoding/payloads/id_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT id_payload.lo -MD -MP -MF $(DEPDIR)/id_payload.Tpo -c -o id_payload.lo `test -f 'encoding/payloads/id_payload.c' || echo '$(srcdir)/'`encoding/payloads/id_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/id_payload.Tpo $(DEPDIR)/id_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/id_payload.c' object='id_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o id_payload.lo `test -f 'encoding/payloads/id_payload.c' || echo '$(srcdir)/'`encoding/payloads/id_payload.c
+
+ike_header.lo: encoding/payloads/ike_header.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_header.lo -MD -MP -MF $(DEPDIR)/ike_header.Tpo -c -o ike_header.lo `test -f 'encoding/payloads/ike_header.c' || echo '$(srcdir)/'`encoding/payloads/ike_header.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_header.Tpo $(DEPDIR)/ike_header.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ike_header.c' object='ike_header.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_header.lo `test -f 'encoding/payloads/ike_header.c' || echo '$(srcdir)/'`encoding/payloads/ike_header.c
+
+ke_payload.lo: encoding/payloads/ke_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ke_payload.lo -MD -MP -MF $(DEPDIR)/ke_payload.Tpo -c -o ke_payload.lo `test -f 'encoding/payloads/ke_payload.c' || echo '$(srcdir)/'`encoding/payloads/ke_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ke_payload.Tpo $(DEPDIR)/ke_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ke_payload.c' object='ke_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ke_payload.lo `test -f 'encoding/payloads/ke_payload.c' || echo '$(srcdir)/'`encoding/payloads/ke_payload.c
+
+nonce_payload.lo: encoding/payloads/nonce_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nonce_payload.lo -MD -MP -MF $(DEPDIR)/nonce_payload.Tpo -c -o nonce_payload.lo `test -f 'encoding/payloads/nonce_payload.c' || echo '$(srcdir)/'`encoding/payloads/nonce_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nonce_payload.Tpo $(DEPDIR)/nonce_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/nonce_payload.c' object='nonce_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nonce_payload.lo `test -f 'encoding/payloads/nonce_payload.c' || echo '$(srcdir)/'`encoding/payloads/nonce_payload.c
+
+notify_payload.lo: encoding/payloads/notify_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT notify_payload.lo -MD -MP -MF $(DEPDIR)/notify_payload.Tpo -c -o notify_payload.lo `test -f 'encoding/payloads/notify_payload.c' || echo '$(srcdir)/'`encoding/payloads/notify_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/notify_payload.Tpo $(DEPDIR)/notify_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/notify_payload.c' object='notify_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o notify_payload.lo `test -f 'encoding/payloads/notify_payload.c' || echo '$(srcdir)/'`encoding/payloads/notify_payload.c
+
+payload.lo: encoding/payloads/payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT payload.lo -MD -MP -MF $(DEPDIR)/payload.Tpo -c -o payload.lo `test -f 'encoding/payloads/payload.c' || echo '$(srcdir)/'`encoding/payloads/payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/payload.Tpo $(DEPDIR)/payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/payload.c' object='payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o payload.lo `test -f 'encoding/payloads/payload.c' || echo '$(srcdir)/'`encoding/payloads/payload.c
+
+proposal_substructure.lo: encoding/payloads/proposal_substructure.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal_substructure.lo -MD -MP -MF $(DEPDIR)/proposal_substructure.Tpo -c -o proposal_substructure.lo `test -f 'encoding/payloads/proposal_substructure.c' || echo '$(srcdir)/'`encoding/payloads/proposal_substructure.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal_substructure.Tpo $(DEPDIR)/proposal_substructure.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/proposal_substructure.c' object='proposal_substructure.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal_substructure.lo `test -f 'encoding/payloads/proposal_substructure.c' || echo '$(srcdir)/'`encoding/payloads/proposal_substructure.c
+
+sa_payload.lo: encoding/payloads/sa_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sa_payload.lo -MD -MP -MF $(DEPDIR)/sa_payload.Tpo -c -o sa_payload.lo `test -f 'encoding/payloads/sa_payload.c' || echo '$(srcdir)/'`encoding/payloads/sa_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sa_payload.Tpo $(DEPDIR)/sa_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/sa_payload.c' object='sa_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sa_payload.lo `test -f 'encoding/payloads/sa_payload.c' || echo '$(srcdir)/'`encoding/payloads/sa_payload.c
+
+traffic_selector_substructure.lo: encoding/payloads/traffic_selector_substructure.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT traffic_selector_substructure.lo -MD -MP -MF $(DEPDIR)/traffic_selector_substructure.Tpo -c -o traffic_selector_substructure.lo `test -f 'encoding/payloads/traffic_selector_substructure.c' || echo '$(srcdir)/'`encoding/payloads/traffic_selector_substructure.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/traffic_selector_substructure.Tpo $(DEPDIR)/traffic_selector_substructure.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/traffic_selector_substructure.c' object='traffic_selector_substructure.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o traffic_selector_substructure.lo `test -f 'encoding/payloads/traffic_selector_substructure.c' || echo '$(srcdir)/'`encoding/payloads/traffic_selector_substructure.c
+
+transform_attribute.lo: encoding/payloads/transform_attribute.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_attribute.lo -MD -MP -MF $(DEPDIR)/transform_attribute.Tpo -c -o transform_attribute.lo `test -f 'encoding/payloads/transform_attribute.c' || echo '$(srcdir)/'`encoding/payloads/transform_attribute.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_attribute.Tpo $(DEPDIR)/transform_attribute.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_attribute.c' object='transform_attribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_attribute.lo `test -f 'encoding/payloads/transform_attribute.c' || echo '$(srcdir)/'`encoding/payloads/transform_attribute.c
+
+transform_substructure.lo: encoding/payloads/transform_substructure.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT transform_substructure.lo -MD -MP -MF $(DEPDIR)/transform_substructure.Tpo -c -o transform_substructure.lo `test -f 'encoding/payloads/transform_substructure.c' || echo '$(srcdir)/'`encoding/payloads/transform_substructure.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/transform_substructure.Tpo $(DEPDIR)/transform_substructure.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/transform_substructure.c' object='transform_substructure.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o transform_substructure.lo `test -f 'encoding/payloads/transform_substructure.c' || echo '$(srcdir)/'`encoding/payloads/transform_substructure.c
+
+ts_payload.lo: encoding/payloads/ts_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ts_payload.lo -MD -MP -MF $(DEPDIR)/ts_payload.Tpo -c -o ts_payload.lo `test -f 'encoding/payloads/ts_payload.c' || echo '$(srcdir)/'`encoding/payloads/ts_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ts_payload.Tpo $(DEPDIR)/ts_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/ts_payload.c' object='ts_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ts_payload.lo `test -f 'encoding/payloads/ts_payload.c' || echo '$(srcdir)/'`encoding/payloads/ts_payload.c
+
+unknown_payload.lo: encoding/payloads/unknown_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unknown_payload.lo -MD -MP -MF $(DEPDIR)/unknown_payload.Tpo -c -o unknown_payload.lo `test -f 'encoding/payloads/unknown_payload.c' || echo '$(srcdir)/'`encoding/payloads/unknown_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unknown_payload.Tpo $(DEPDIR)/unknown_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/unknown_payload.c' object='unknown_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unknown_payload.lo `test -f 'encoding/payloads/unknown_payload.c' || echo '$(srcdir)/'`encoding/payloads/unknown_payload.c
+
+vendor_id_payload.lo: encoding/payloads/vendor_id_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vendor_id_payload.lo -MD -MP -MF $(DEPDIR)/vendor_id_payload.Tpo -c -o vendor_id_payload.lo `test -f 'encoding/payloads/vendor_id_payload.c' || echo '$(srcdir)/'`encoding/payloads/vendor_id_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/vendor_id_payload.Tpo $(DEPDIR)/vendor_id_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/vendor_id_payload.c' object='vendor_id_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vendor_id_payload.lo `test -f 'encoding/payloads/vendor_id_payload.c' || echo '$(srcdir)/'`encoding/payloads/vendor_id_payload.c
+
+kernel_interface.lo: kernel/kernel_interface.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_interface.lo -MD -MP -MF $(DEPDIR)/kernel_interface.Tpo -c -o kernel_interface.lo `test -f 'kernel/kernel_interface.c' || echo '$(srcdir)/'`kernel/kernel_interface.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_interface.Tpo $(DEPDIR)/kernel_interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_interface.c' object='kernel_interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_interface.lo `test -f 'kernel/kernel_interface.c' || echo '$(srcdir)/'`kernel/kernel_interface.c
+
+kernel_ipsec.lo: kernel/kernel_ipsec.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_ipsec.lo -MD -MP -MF $(DEPDIR)/kernel_ipsec.Tpo -c -o kernel_ipsec.lo `test -f 'kernel/kernel_ipsec.c' || echo '$(srcdir)/'`kernel/kernel_ipsec.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_ipsec.Tpo $(DEPDIR)/kernel_ipsec.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kernel/kernel_ipsec.c' object='kernel_ipsec.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kernel_ipsec.lo `test -f 'kernel/kernel_ipsec.c' || echo '$(srcdir)/'`kernel/kernel_ipsec.c
+
+packet.lo: network/packet.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.lo -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.lo `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/packet.c' object='packet.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.lo `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
+
+receiver.lo: network/receiver.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT receiver.lo -MD -MP -MF $(DEPDIR)/receiver.Tpo -c -o receiver.lo `test -f 'network/receiver.c' || echo '$(srcdir)/'`network/receiver.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/receiver.Tpo $(DEPDIR)/receiver.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/receiver.c' object='receiver.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o receiver.lo `test -f 'network/receiver.c' || echo '$(srcdir)/'`network/receiver.c
+
+sender.lo: network/sender.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sender.lo -MD -MP -MF $(DEPDIR)/sender.Tpo -c -o sender.lo `test -f 'network/sender.c' || echo '$(srcdir)/'`network/sender.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sender.Tpo $(DEPDIR)/sender.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/sender.c' object='sender.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sender.lo `test -f 'network/sender.c' || echo '$(srcdir)/'`network/sender.c
+
+socket_manager.lo: network/socket_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket_manager.lo -MD -MP -MF $(DEPDIR)/socket_manager.Tpo -c -o socket_manager.lo `test -f 'network/socket_manager.c' || echo '$(srcdir)/'`network/socket_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket_manager.Tpo $(DEPDIR)/socket_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/socket_manager.c' object='socket_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket_manager.lo `test -f 'network/socket_manager.c' || echo '$(srcdir)/'`network/socket_manager.c
+
+acquire_job.lo: processing/jobs/acquire_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acquire_job.lo -MD -MP -MF $(DEPDIR)/acquire_job.Tpo -c -o acquire_job.lo `test -f 'processing/jobs/acquire_job.c' || echo '$(srcdir)/'`processing/jobs/acquire_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acquire_job.Tpo $(DEPDIR)/acquire_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/acquire_job.c' object='acquire_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acquire_job.lo `test -f 'processing/jobs/acquire_job.c' || echo '$(srcdir)/'`processing/jobs/acquire_job.c
+
+callback_job.lo: processing/jobs/callback_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT callback_job.lo -MD -MP -MF $(DEPDIR)/callback_job.Tpo -c -o callback_job.lo `test -f 'processing/jobs/callback_job.c' || echo '$(srcdir)/'`processing/jobs/callback_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/callback_job.Tpo $(DEPDIR)/callback_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/callback_job.c' object='callback_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o callback_job.lo `test -f 'processing/jobs/callback_job.c' || echo '$(srcdir)/'`processing/jobs/callback_job.c
+
+delete_child_sa_job.lo: processing/jobs/delete_child_sa_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_child_sa_job.lo -MD -MP -MF $(DEPDIR)/delete_child_sa_job.Tpo -c -o delete_child_sa_job.lo `test -f 'processing/jobs/delete_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_child_sa_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_child_sa_job.Tpo $(DEPDIR)/delete_child_sa_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_child_sa_job.c' object='delete_child_sa_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_child_sa_job.lo `test -f 'processing/jobs/delete_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_child_sa_job.c
+
+delete_ike_sa_job.lo: processing/jobs/delete_ike_sa_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT delete_ike_sa_job.lo -MD -MP -MF $(DEPDIR)/delete_ike_sa_job.Tpo -c -o delete_ike_sa_job.lo `test -f 'processing/jobs/delete_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_ike_sa_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/delete_ike_sa_job.Tpo $(DEPDIR)/delete_ike_sa_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/delete_ike_sa_job.c' object='delete_ike_sa_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_ike_sa_job.lo `test -f 'processing/jobs/delete_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/delete_ike_sa_job.c
+
+migrate_job.lo: processing/jobs/migrate_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT migrate_job.lo -MD -MP -MF $(DEPDIR)/migrate_job.Tpo -c -o migrate_job.lo `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/migrate_job.Tpo $(DEPDIR)/migrate_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/migrate_job.c' object='migrate_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o migrate_job.lo `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
+
+process_message_job.lo: processing/jobs/process_message_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_message_job.lo -MD -MP -MF $(DEPDIR)/process_message_job.Tpo -c -o process_message_job.lo `test -f 'processing/jobs/process_message_job.c' || echo '$(srcdir)/'`processing/jobs/process_message_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/process_message_job.Tpo $(DEPDIR)/process_message_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/process_message_job.c' object='process_message_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_message_job.lo `test -f 'processing/jobs/process_message_job.c' || echo '$(srcdir)/'`processing/jobs/process_message_job.c
+
+rekey_child_sa_job.lo: processing/jobs/rekey_child_sa_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_child_sa_job.lo -MD -MP -MF $(DEPDIR)/rekey_child_sa_job.Tpo -c -o rekey_child_sa_job.lo `test -f 'processing/jobs/rekey_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_child_sa_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_child_sa_job.Tpo $(DEPDIR)/rekey_child_sa_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_child_sa_job.c' object='rekey_child_sa_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_child_sa_job.lo `test -f 'processing/jobs/rekey_child_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_child_sa_job.c
+
+rekey_ike_sa_job.lo: processing/jobs/rekey_ike_sa_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rekey_ike_sa_job.lo -MD -MP -MF $(DEPDIR)/rekey_ike_sa_job.Tpo -c -o rekey_ike_sa_job.lo `test -f 'processing/jobs/rekey_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_ike_sa_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rekey_ike_sa_job.Tpo $(DEPDIR)/rekey_ike_sa_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/rekey_ike_sa_job.c' object='rekey_ike_sa_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rekey_ike_sa_job.lo `test -f 'processing/jobs/rekey_ike_sa_job.c' || echo '$(srcdir)/'`processing/jobs/rekey_ike_sa_job.c
+
+retransmit_job.lo: processing/jobs/retransmit_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retransmit_job.lo -MD -MP -MF $(DEPDIR)/retransmit_job.Tpo -c -o retransmit_job.lo `test -f 'processing/jobs/retransmit_job.c' || echo '$(srcdir)/'`processing/jobs/retransmit_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/retransmit_job.Tpo $(DEPDIR)/retransmit_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/retransmit_job.c' object='retransmit_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retransmit_job.lo `test -f 'processing/jobs/retransmit_job.c' || echo '$(srcdir)/'`processing/jobs/retransmit_job.c
+
+send_dpd_job.lo: processing/jobs/send_dpd_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_dpd_job.lo -MD -MP -MF $(DEPDIR)/send_dpd_job.Tpo -c -o send_dpd_job.lo `test -f 'processing/jobs/send_dpd_job.c' || echo '$(srcdir)/'`processing/jobs/send_dpd_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_dpd_job.Tpo $(DEPDIR)/send_dpd_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_dpd_job.c' object='send_dpd_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_dpd_job.lo `test -f 'processing/jobs/send_dpd_job.c' || echo '$(srcdir)/'`processing/jobs/send_dpd_job.c
+
+send_keepalive_job.lo: processing/jobs/send_keepalive_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_keepalive_job.lo -MD -MP -MF $(DEPDIR)/send_keepalive_job.Tpo -c -o send_keepalive_job.lo `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_keepalive_job.Tpo $(DEPDIR)/send_keepalive_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/send_keepalive_job.c' object='send_keepalive_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_keepalive_job.lo `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c
+
+roam_job.lo: processing/jobs/roam_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT roam_job.lo -MD -MP -MF $(DEPDIR)/roam_job.Tpo -c -o roam_job.lo `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/roam_job.Tpo $(DEPDIR)/roam_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/roam_job.c' object='roam_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o roam_job.lo `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c
+
+update_sa_job.lo: processing/jobs/update_sa_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT update_sa_job.lo -MD -MP -MF $(DEPDIR)/update_sa_job.Tpo -c -o update_sa_job.lo `test -f 'processing/jobs/update_sa_job.c' || echo '$(srcdir)/'`processing/jobs/update_sa_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/update_sa_job.Tpo $(DEPDIR)/update_sa_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/update_sa_job.c' object='update_sa_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o update_sa_job.lo `test -f 'processing/jobs/update_sa_job.c' || echo '$(srcdir)/'`processing/jobs/update_sa_job.c
+
+inactivity_job.lo: processing/jobs/inactivity_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inactivity_job.lo -MD -MP -MF $(DEPDIR)/inactivity_job.Tpo -c -o inactivity_job.lo `test -f 'processing/jobs/inactivity_job.c' || echo '$(srcdir)/'`processing/jobs/inactivity_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/inactivity_job.Tpo $(DEPDIR)/inactivity_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/inactivity_job.c' object='inactivity_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inactivity_job.lo `test -f 'processing/jobs/inactivity_job.c' || echo '$(srcdir)/'`processing/jobs/inactivity_job.c
+
+scheduler.lo: processing/scheduler.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT scheduler.lo -MD -MP -MF $(DEPDIR)/scheduler.Tpo -c -o scheduler.lo `test -f 'processing/scheduler.c' || echo '$(srcdir)/'`processing/scheduler.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/scheduler.Tpo $(DEPDIR)/scheduler.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/scheduler.c' object='scheduler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o scheduler.lo `test -f 'processing/scheduler.c' || echo '$(srcdir)/'`processing/scheduler.c
+
+processor.lo: processing/processor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT processor.lo -MD -MP -MF $(DEPDIR)/processor.Tpo -c -o processor.lo `test -f 'processing/processor.c' || echo '$(srcdir)/'`processing/processor.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/processor.Tpo $(DEPDIR)/processor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/processor.c' object='processor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o processor.lo `test -f 'processing/processor.c' || echo '$(srcdir)/'`processing/processor.c
+
+authenticator.lo: sa/authenticators/authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT authenticator.lo -MD -MP -MF $(DEPDIR)/authenticator.Tpo -c -o authenticator.lo `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/authenticator.Tpo $(DEPDIR)/authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/authenticator.c' object='authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o authenticator.lo `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
+
+eap_authenticator.lo: sa/authenticators/eap_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_authenticator.lo -MD -MP -MF $(DEPDIR)/eap_authenticator.Tpo -c -o eap_authenticator.lo `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_authenticator.Tpo $(DEPDIR)/eap_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap_authenticator.c' object='eap_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_authenticator.lo `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
+
+eap_method.lo: sa/authenticators/eap/eap_method.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_method.lo -MD -MP -MF $(DEPDIR)/eap_method.Tpo -c -o eap_method.lo `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_method.Tpo $(DEPDIR)/eap_method.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_method.c' object='eap_method.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.lo `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
+
+eap_manager.lo: sa/authenticators/eap/eap_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.lo -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.lo `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.lo `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
+
+sim_manager.lo: sa/authenticators/eap/sim_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sim_manager.lo -MD -MP -MF $(DEPDIR)/sim_manager.Tpo -c -o sim_manager.lo `test -f 'sa/authenticators/eap/sim_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sim_manager.Tpo $(DEPDIR)/sim_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/sim_manager.c' object='sim_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sim_manager.lo `test -f 'sa/authenticators/eap/sim_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim_manager.c
+
+psk_authenticator.lo: sa/authenticators/psk_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.lo -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.lo `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/psk_authenticator.c' object='psk_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.lo `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
+
+pubkey_authenticator.lo: sa/authenticators/pubkey_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.lo -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.lo `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.lo `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
+
+child_sa.lo: sa/child_sa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_sa.lo -MD -MP -MF $(DEPDIR)/child_sa.Tpo -c -o child_sa.lo `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_sa.Tpo $(DEPDIR)/child_sa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/child_sa.c' object='child_sa.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_sa.lo `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c
+
+ike_sa.lo: sa/ike_sa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa.lo -MD -MP -MF $(DEPDIR)/ike_sa.Tpo -c -o ike_sa.lo `test -f 'sa/ike_sa.c' || echo '$(srcdir)/'`sa/ike_sa.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa.Tpo $(DEPDIR)/ike_sa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa.c' object='ike_sa.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa.lo `test -f 'sa/ike_sa.c' || echo '$(srcdir)/'`sa/ike_sa.c
+
+ike_sa_id.lo: sa/ike_sa_id.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_id.lo -MD -MP -MF $(DEPDIR)/ike_sa_id.Tpo -c -o ike_sa_id.lo `test -f 'sa/ike_sa_id.c' || echo '$(srcdir)/'`sa/ike_sa_id.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_id.Tpo $(DEPDIR)/ike_sa_id.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_id.c' object='ike_sa_id.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_id.lo `test -f 'sa/ike_sa_id.c' || echo '$(srcdir)/'`sa/ike_sa_id.c
+
+ike_sa_manager.lo: sa/ike_sa_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_manager.lo -MD -MP -MF $(DEPDIR)/ike_sa_manager.Tpo -c -o ike_sa_manager.lo `test -f 'sa/ike_sa_manager.c' || echo '$(srcdir)/'`sa/ike_sa_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_manager.Tpo $(DEPDIR)/ike_sa_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ike_sa_manager.c' object='ike_sa_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_manager.lo `test -f 'sa/ike_sa_manager.c' || echo '$(srcdir)/'`sa/ike_sa_manager.c
+
+task_manager.lo: sa/task_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_manager.lo -MD -MP -MF $(DEPDIR)/task_manager.Tpo -c -o task_manager.lo `test -f 'sa/task_manager.c' || echo '$(srcdir)/'`sa/task_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task_manager.Tpo $(DEPDIR)/task_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/task_manager.c' object='task_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager.lo `test -f 'sa/task_manager.c' || echo '$(srcdir)/'`sa/task_manager.c
+
+keymat.lo: sa/keymat.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.lo -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+
+trap_manager.lo: sa/trap_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT trap_manager.lo -MD -MP -MF $(DEPDIR)/trap_manager.Tpo -c -o trap_manager.lo `test -f 'sa/trap_manager.c' || echo '$(srcdir)/'`sa/trap_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/trap_manager.Tpo $(DEPDIR)/trap_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/trap_manager.c' object='trap_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o trap_manager.lo `test -f 'sa/trap_manager.c' || echo '$(srcdir)/'`sa/trap_manager.c
+
+child_create.lo: sa/tasks/child_create.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.lo -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.lo `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_create.Tpo $(DEPDIR)/child_create.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_create.c' object='child_create.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_create.lo `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
+
+child_delete.lo: sa/tasks/child_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_delete.lo -MD -MP -MF $(DEPDIR)/child_delete.Tpo -c -o child_delete.lo `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_delete.Tpo $(DEPDIR)/child_delete.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_delete.c' object='child_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_delete.lo `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
+
+child_rekey.lo: sa/tasks/child_rekey.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_rekey.lo -MD -MP -MF $(DEPDIR)/child_rekey.Tpo -c -o child_rekey.lo `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_rekey.Tpo $(DEPDIR)/child_rekey.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_rekey.c' object='child_rekey.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_rekey.lo `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
+
+ike_auth.lo: sa/tasks/ike_auth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth.lo -MD -MP -MF $(DEPDIR)/ike_auth.Tpo -c -o ike_auth.lo `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth.Tpo $(DEPDIR)/ike_auth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth.c' object='ike_auth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.lo `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
+
+ike_cert_pre.lo: sa/tasks/ike_cert_pre.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.lo -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.lo `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.lo `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
+
+ike_cert_post.lo: sa/tasks/ike_cert_post.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.lo -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.lo `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.lo `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
+
+ike_config.lo: sa/tasks/ike_config.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.lo -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.lo `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_config.Tpo $(DEPDIR)/ike_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_config.c' object='ike_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_config.lo `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
+
+ike_delete.lo: sa/tasks/ike_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_delete.lo -MD -MP -MF $(DEPDIR)/ike_delete.Tpo -c -o ike_delete.lo `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_delete.Tpo $(DEPDIR)/ike_delete.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_delete.c' object='ike_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_delete.lo `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
+
+ike_dpd.lo: sa/tasks/ike_dpd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_dpd.lo -MD -MP -MF $(DEPDIR)/ike_dpd.Tpo -c -o ike_dpd.lo `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_dpd.Tpo $(DEPDIR)/ike_dpd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_dpd.c' object='ike_dpd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_dpd.lo `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
+
+ike_init.lo: sa/tasks/ike_init.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_init.lo -MD -MP -MF $(DEPDIR)/ike_init.Tpo -c -o ike_init.lo `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_init.Tpo $(DEPDIR)/ike_init.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_init.c' object='ike_init.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_init.lo `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
+
+ike_natd.lo: sa/tasks/ike_natd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_natd.lo -MD -MP -MF $(DEPDIR)/ike_natd.Tpo -c -o ike_natd.lo `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_natd.Tpo $(DEPDIR)/ike_natd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_natd.c' object='ike_natd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_natd.lo `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
+
+ike_mobike.lo: sa/tasks/ike_mobike.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_mobike.lo -MD -MP -MF $(DEPDIR)/ike_mobike.Tpo -c -o ike_mobike.lo `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_mobike.Tpo $(DEPDIR)/ike_mobike.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_mobike.c' object='ike_mobike.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_mobike.lo `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
+
+ike_rekey.lo: sa/tasks/ike_rekey.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_rekey.lo -MD -MP -MF $(DEPDIR)/ike_rekey.Tpo -c -o ike_rekey.lo `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_rekey.Tpo $(DEPDIR)/ike_rekey.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_rekey.c' object='ike_rekey.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_rekey.lo `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
+
+ike_reauth.lo: sa/tasks/ike_reauth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_reauth.lo -MD -MP -MF $(DEPDIR)/ike_reauth.Tpo -c -o ike_reauth.lo `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_reauth.Tpo $(DEPDIR)/ike_reauth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_reauth.c' object='ike_reauth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_reauth.lo `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
+
+ike_auth_lifetime.lo: sa/tasks/ike_auth_lifetime.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_lifetime.lo -MD -MP -MF $(DEPDIR)/ike_auth_lifetime.Tpo -c -o ike_auth_lifetime.lo `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_lifetime.Tpo $(DEPDIR)/ike_auth_lifetime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth_lifetime.c' object='ike_auth_lifetime.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_lifetime.lo `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
+
+ike_vendor.lo: sa/tasks/ike_vendor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_vendor.lo -MD -MP -MF $(DEPDIR)/ike_vendor.Tpo -c -o ike_vendor.lo `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_vendor.Tpo $(DEPDIR)/ike_vendor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_vendor.c' object='ike_vendor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_vendor.lo `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
+
+task.lo: sa/tasks/task.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.lo -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/task.c' object='task.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
+
+credential_manager.lo: credentials/credential_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.lo -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
+
+auth_cfg_wrapper.lo: credentials/sets/auth_cfg_wrapper.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.lo -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
+
+ocsp_response_wrapper.lo: credentials/sets/ocsp_response_wrapper.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.lo -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
+
+cert_cache.lo: credentials/sets/cert_cache.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.lo -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
+
+endpoint_notify.lo: encoding/payloads/endpoint_notify.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.lo -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/endpoint_notify.Tpo $(DEPDIR)/endpoint_notify.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/endpoint_notify.c' object='endpoint_notify.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
+
+initiate_mediation_job.lo: processing/jobs/initiate_mediation_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT initiate_mediation_job.lo -MD -MP -MF $(DEPDIR)/initiate_mediation_job.Tpo -c -o initiate_mediation_job.lo `test -f 'processing/jobs/initiate_mediation_job.c' || echo '$(srcdir)/'`processing/jobs/initiate_mediation_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/initiate_mediation_job.Tpo $(DEPDIR)/initiate_mediation_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/initiate_mediation_job.c' object='initiate_mediation_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o initiate_mediation_job.lo `test -f 'processing/jobs/initiate_mediation_job.c' || echo '$(srcdir)/'`processing/jobs/initiate_mediation_job.c
+
+mediation_job.lo: processing/jobs/mediation_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_job.lo -MD -MP -MF $(DEPDIR)/mediation_job.Tpo -c -o mediation_job.lo `test -f 'processing/jobs/mediation_job.c' || echo '$(srcdir)/'`processing/jobs/mediation_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_job.Tpo $(DEPDIR)/mediation_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/mediation_job.c' object='mediation_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_job.lo `test -f 'processing/jobs/mediation_job.c' || echo '$(srcdir)/'`processing/jobs/mediation_job.c
+
+connect_manager.lo: sa/connect_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT connect_manager.lo -MD -MP -MF $(DEPDIR)/connect_manager.Tpo -c -o connect_manager.lo `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/connect_manager.Tpo $(DEPDIR)/connect_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/connect_manager.c' object='connect_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o connect_manager.lo `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
+
+mediation_manager.lo: sa/mediation_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_manager.lo -MD -MP -MF $(DEPDIR)/mediation_manager.Tpo -c -o mediation_manager.lo `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_manager.Tpo $(DEPDIR)/mediation_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/mediation_manager.c' object='mediation_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.lo `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
+
+ike_me.lo: sa/tasks/ike_me.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.lo -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.lo `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.lo `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _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.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; 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"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+ 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-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-libLTLIBRARIES
+
+
+daemon.lo : $(top_builddir)/config.status
+
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@ # otherwise this library is linked to both the eap_aka and the eap_sim plugin
+
+# 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/bus/bus.c b/src/libcharon/bus/bus.c
new file mode 100644
index 000000000..764744a41
--- /dev/null
+++ b/src/libcharon/bus/bus.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2006 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 "bus.h"
+
+#include <stdint.h>
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/thread_value.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+typedef struct private_bus_t private_bus_t;
+
+/**
+ * Private data of a bus_t object.
+ */
+struct private_bus_t {
+ /**
+ * Public part of a bus_t object.
+ */
+ bus_t public;
+
+ /**
+ * List of registered listeners as entry_t's
+ */
+ linked_list_t *listeners;
+
+ /**
+ * mutex to synchronize active listeners, recursively
+ */
+ mutex_t *mutex;
+
+ /**
+ * Thread local storage the threads IKE_SA
+ */
+ thread_value_t *thread_sa;
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * a listener entry, either active or passive
+ */
+struct entry_t {
+
+ /**
+ * registered listener interface
+ */
+ listener_t *listener;
+
+ /**
+ * is this a active listen() call with a blocking thread
+ */
+ bool blocker;
+
+ /**
+ * are we currently calling this listener
+ */
+ int calling;
+
+ /**
+ * condvar where active listeners wait
+ */
+ condvar_t *condvar;
+};
+
+/**
+ * create a listener entry
+ */
+static entry_t *entry_create(listener_t *listener, bool blocker)
+{
+ entry_t *this = malloc_thing(entry_t);
+
+ this->listener = listener;
+ this->blocker = blocker;
+ this->calling = 0;
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+ return this;
+}
+
+/**
+ * destroy an entry_t
+ */
+static void entry_destroy(entry_t *entry)
+{
+ entry->condvar->destroy(entry->condvar);
+ free(entry);
+}
+
+/**
+ * Implementation of bus_t.add_listener.
+ */
+static void add_listener(private_bus_t *this, listener_t *listener)
+{
+ this->mutex->lock(this->mutex);
+ this->listeners->insert_last(this->listeners, entry_create(listener, FALSE));
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.remove_listener.
+ */
+static void remove_listener(private_bus_t *this, listener_t *listener)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->listener == listener)
+ {
+ this->listeners->remove_at(this->listeners, enumerator);
+ entry_destroy(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+typedef struct cleanup_data_t cleanup_data_t;
+
+/**
+ * data to remove a listener using thread_cleanup_t handler
+ */
+struct cleanup_data_t {
+ /** bus instance */
+ private_bus_t *this;
+ /** listener entry */
+ entry_t *entry;
+};
+
+/**
+ * thread_cleanup_t handler to remove a listener
+ */
+static void listener_cleanup(cleanup_data_t *data)
+{
+ data->this->listeners->remove(data->this->listeners, data->entry, NULL);
+ entry_destroy(data->entry);
+}
+
+/**
+ * Implementation of bus_t.listen.
+ */
+static void listen_(private_bus_t *this, listener_t *listener, job_t *job)
+{
+ bool old;
+ cleanup_data_t data;
+
+ data.this = this;
+ data.entry = entry_create(listener, TRUE);
+
+ this->mutex->lock(this->mutex);
+ this->listeners->insert_last(this->listeners, data.entry);
+ charon->processor->queue_job(charon->processor, job);
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ thread_cleanup_push((thread_cleanup_t)listener_cleanup, &data);
+ old = thread_cancelability(TRUE);
+ while (data.entry->blocker)
+ {
+ data.entry->condvar->wait(data.entry->condvar, this->mutex);
+ }
+ thread_cancelability(old);
+ thread_cleanup_pop(FALSE);
+ /* unlock mutex */
+ thread_cleanup_pop(TRUE);
+ entry_destroy(data.entry);
+}
+
+/**
+ * Implementation of bus_t.set_sa.
+ */
+static void set_sa(private_bus_t *this, ike_sa_t *ike_sa)
+{
+ this->thread_sa->set(this->thread_sa, ike_sa);
+}
+
+/**
+ * Implementation of bus_t.get_sa
+ */
+static ike_sa_t* get_sa(private_bus_t *this)
+{
+ return this->thread_sa->get(this->thread_sa);
+}
+
+/**
+ * data associated to a signal, passed to callback
+ */
+typedef struct {
+ /** associated IKE_SA */
+ ike_sa_t *ike_sa;
+ /** invoking thread */
+ long thread;
+ /** debug group */
+ debug_t group;
+ /** debug level */
+ level_t level;
+ /** format string */
+ char *format;
+ /** argument list */
+ va_list args;
+} log_data_t;
+
+/**
+ * listener->log() invocation as a list remove callback
+ */
+static bool log_cb(entry_t *entry, log_data_t *data)
+{
+ va_list args;
+
+ if (entry->calling || !entry->listener->log)
+ { /* avoid recursive calls */
+ return FALSE;
+ }
+ entry->calling++;
+ va_copy(args, data->args);
+ if (!entry->listener->log(entry->listener, data->group, data->level,
+ data->thread, data->ike_sa, data->format, args))
+ {
+ if (entry->blocker)
+ {
+ entry->blocker = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ else
+ {
+ entry_destroy(entry);
+ }
+ va_end(args);
+ entry->calling--;
+ return TRUE;
+ }
+ va_end(args);
+ entry->calling--;
+ return FALSE;
+}
+
+/**
+ * Implementation of bus_t.vlog.
+ */
+static void vlog(private_bus_t *this, debug_t group, level_t level,
+ char* format, va_list args)
+{
+ log_data_t data;
+
+ data.ike_sa = this->thread_sa->get(this->thread_sa);
+ data.thread = thread_current_id();
+ data.group = group;
+ data.level = level;
+ data.format = format;
+ va_copy(data.args, args);
+
+ this->mutex->lock(this->mutex);
+ /* We use the remove() method to invoke all listeners. This is cheap and
+ * does not require an allocation for this performance critical function. */
+ this->listeners->remove(this->listeners, &data, (void*)log_cb);
+ this->mutex->unlock(this->mutex);
+
+ va_end(data.args);
+}
+
+/**
+ * Implementation of bus_t.log.
+ */
+static void log_(private_bus_t *this, debug_t group, level_t level,
+ char* format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vlog(this, group, level, format, args);
+ va_end(args);
+}
+
+/**
+ * unregister a listener
+ */
+static void unregister_listener(private_bus_t *this, entry_t *entry,
+ enumerator_t *enumerator)
+{
+ if (entry->blocker)
+ {
+ entry->blocker = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ else
+ {
+ entry_destroy(entry);
+ }
+ this->listeners->remove_at(this->listeners, enumerator);
+}
+
+/**
+ * Implementation of bus_t.alert
+ */
+static void alert(private_bus_t *this, alert_t alert, ...)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ va_list args;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->alert)
+ {
+ continue;
+ }
+ entry->calling++;
+ va_start(args, alert);
+ keep = entry->listener->alert(entry->listener, ike_sa, alert, args);
+ va_end(args);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.ike_state_change
+ */
+static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_state_change)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_state_change(entry->listener, ike_sa, state);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_state_change
+ */
+static void child_state_change(private_bus_t *this, child_sa_t *child_sa,
+ child_sa_state_t state)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_state_change)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_state_change(entry->listener, ike_sa,
+ child_sa, state);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.message
+ */
+static void message(private_bus_t *this, message_t *message, bool incoming)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->message)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->message(entry->listener, ike_sa,
+ message, incoming);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.ike_keys
+ */
+static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_keys)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_keys(entry->listener, ike_sa, dh,
+ nonce_i, nonce_r, rekey);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_keys
+ */
+static void child_keys(private_bus_t *this, child_sa_t *child_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_keys)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa,
+ dh, nonce_i, nonce_r);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_updown
+ */
+static void child_updown(private_bus_t *this, child_sa_t *child_sa, bool up)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_updown)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_updown(entry->listener,
+ ike_sa, child_sa, up);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_rekey
+ */
+static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_rekey)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_rekey(entry->listener, ike_sa, old, new);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.ike_updown
+ */
+static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_updown)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_updown(entry->listener, ike_sa, up);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ /* a down event for IKE_SA implicitly downs all CHILD_SAs */
+ if (!up)
+ {
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ child_updown(this, child_sa, FALSE);
+ }
+ iterator->destroy(iterator);
+ }
+}
+
+/**
+ * Implementation of bus_t.ike_rekey
+ */
+static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_rekey)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_rekey(entry->listener, old, new);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.authorize
+ */
+static bool authorize(private_bus_t *this, bool final)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep, success = TRUE;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->authorize)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->authorize(entry->listener, ike_sa,
+ final, &success);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ if (!success)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+ return success;
+}
+
+/**
+ * Implementation of bus_t.destroy.
+ */
+static void destroy(private_bus_t *this)
+{
+ this->thread_sa->destroy(this->thread_sa);
+ this->mutex->destroy(this->mutex);
+ this->listeners->destroy_function(this->listeners, (void*)entry_destroy);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+bus_t *bus_create()
+{
+ private_bus_t *this = malloc_thing(private_bus_t);
+
+ this->public.add_listener = (void(*)(bus_t*,listener_t*))add_listener;
+ this->public.remove_listener = (void(*)(bus_t*,listener_t*))remove_listener;
+ this->public.listen = (void(*)(bus_t*, listener_t *listener, job_t *job))listen_;
+ this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa;
+ this->public.get_sa = (ike_sa_t*(*)(bus_t*))get_sa;
+ this->public.log = (void(*)(bus_t*,debug_t,level_t,char*,...))log_;
+ this->public.vlog = (void(*)(bus_t*,debug_t,level_t,char*,va_list))vlog;
+ this->public.alert = (void(*)(bus_t*, alert_t alert, ...))alert;
+ this->public.ike_state_change = (void(*)(bus_t*,ike_sa_t*,ike_sa_state_t))ike_state_change;
+ this->public.child_state_change = (void(*)(bus_t*,child_sa_t*,child_sa_state_t))child_state_change;
+ this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message;
+ this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
+ this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
+ this->public.ike_updown = (void(*)(bus_t*, ike_sa_t *ike_sa, bool up))ike_updown;
+ this->public.ike_rekey = (void(*)(bus_t*, ike_sa_t *old, ike_sa_t *new))ike_rekey;
+ this->public.child_updown = (void(*)(bus_t*, child_sa_t *child_sa, bool up))child_updown;
+ this->public.child_rekey = (void(*)(bus_t*, child_sa_t *old, child_sa_t *new))child_rekey;
+ this->public.authorize = (bool(*)(bus_t*, bool final))authorize;
+ this->public.destroy = (void(*)(bus_t*)) destroy;
+
+ this->listeners = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+ this->thread_sa = thread_value_create(NULL);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
new file mode 100644
index 000000000..8cf392eae
--- /dev/null
+++ b/src/libcharon/bus/bus.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2006-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 bus bus
+ * @{ @ingroup libcharon
+ */
+
+#ifndef BUS_H_
+#define BUS_H_
+
+typedef enum alert_t alert_t;
+typedef struct bus_t bus_t;
+
+#include <stdarg.h>
+
+#include <debug.h>
+#include <sa/ike_sa.h>
+#include <sa/child_sa.h>
+#include <processing/jobs/job.h>
+#include <bus/listeners/listener.h>
+
+/* undefine the definitions from libstrongswan */
+#undef DBG0
+#undef DBG1
+#undef DBG2
+#undef DBG3
+#undef DBG4
+
+#ifndef DEBUG_LEVEL
+# define DEBUG_LEVEL 4
+#endif /* DEBUG_LEVEL */
+
+#if DEBUG_LEVEL >= 0
+#define DBG0(group, format, ...) charon->bus->log(charon->bus, group, 0, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 0 */
+#if DEBUG_LEVEL >= 1
+#define DBG1(group, format, ...) charon->bus->log(charon->bus, group, 1, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 1 */
+#if DEBUG_LEVEL >= 2
+#define DBG2(group, format, ...) charon->bus->log(charon->bus, group, 2, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 2 */
+#if DEBUG_LEVEL >= 3
+#define DBG3(group, format, ...) charon->bus->log(charon->bus, group, 3, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 3 */
+#if DEBUG_LEVEL >= 4
+#define DBG4(group, format, ...) charon->bus->log(charon->bus, group, 4, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 4 */
+
+#ifndef DBG0
+# define DBG0(...) {}
+#endif /* DBG0 */
+#ifndef DBG1
+# define DBG1(...) {}
+#endif /* DBG1 */
+#ifndef DBG2
+# define DBG2(...) {}
+#endif /* DBG2 */
+#ifndef DBG3
+# define DBG3(...) {}
+#endif /* DBG3 */
+#ifndef DBG4
+# define DBG4(...) {}
+#endif /* DBG4 */
+
+/**
+ * Kind of alerts to raise.
+ */
+enum alert_t {
+ /* a RADIUS server did not respond, no additional arguments */
+ ALERT_RADIUS_NOT_RESPONDING,
+ /* a shutdown signal has been received, argument is a int with the signal */
+ ALERT_SHUTDOWN_SIGNAL,
+};
+
+/**
+ * The bus receives events and sends them to all registered listeners.
+ *
+ * Any events sent to are delivered to all registered listeners. Threads
+ * may wait actively to events using the blocking listen() call.
+ */
+struct bus_t {
+
+ /**
+ * Register a listener to the bus.
+ *
+ * A registered listener receives all events which are sent to the bus.
+ * The listener is passive; the thread which emitted the event
+ * processes the listener routine.
+ *
+ * @param listener listener to register.
+ */
+ void (*add_listener) (bus_t *this, listener_t *listener);
+
+ /**
+ * Unregister a listener from the bus.
+ *
+ * @param listener listener to unregister.
+ */
+ void (*remove_listener) (bus_t *this, listener_t *listener);
+
+ /**
+ * Register a listener and block the calling thread.
+ *
+ * This call registers a listener and blocks the calling thread until
+ * its listeners function returns FALSE. This allows to wait for certain
+ * events. The associated job is executed after the listener has been
+ * registered: This allows to listen on events we initiate with the job,
+ * without missing any events to job may fire.
+ *
+ * @param listener listener to register
+ * @param job job to execute asynchronously when registered, or NULL
+ */
+ void (*listen)(bus_t *this, listener_t *listener, job_t *job);
+
+ /**
+ * Set the IKE_SA the calling thread is using.
+ *
+ * To associate an received log message to an IKE_SA without passing it as
+ * parameter each time, the thread registers the currenlty used IKE_SA
+ * during check-out. Before check-in, the thread unregisters the IKE_SA.
+ * This IKE_SA is stored per-thread, so each thread has its own IKE_SA
+ * registered.
+ *
+ * @param ike_sa ike_sa to register, or NULL to unregister
+ */
+ void (*set_sa) (bus_t *this, ike_sa_t *ike_sa);
+
+ /**
+ * Get the IKE_SA the calling thread is currently using.
+ *
+ * If a thread currently does not know what IKE_SA it is processing,
+ * it can call get_sa() to look up the SA set during checkout via set_sa().
+ *
+ * @return registered ike_sa, NULL if none registered
+ */
+ ike_sa_t* (*get_sa)(bus_t *this);
+
+ /**
+ * Send a log message to the bus.
+ *
+ * The signal specifies the type of the event occured. The format string
+ * specifies an additional informational or error message with a
+ * printf() like variable argument list.
+ * Use the DBG() macros.
+ *
+ * @param group debugging group
+ * @param level verbosity level of the signal
+ * @param format printf() style format string
+ * @param ... printf() style argument list
+ */
+ void (*log)(bus_t *this, debug_t group, level_t level, char* format, ...);
+
+ /**
+ * Send a log message to the bus using va_list arguments.
+ *
+ * Same as bus_t.signal(), but uses va_list argument list.
+ *
+ * @param group kind of the signal (up, down, rekeyed, ...)
+ * @param level verbosity level of the signal
+ * @param format printf() style format string
+ * @param args va_list arguments
+ */
+ void (*vlog)(bus_t *this, debug_t group, level_t level,
+ char* format, va_list args);
+
+ /**
+ * Raise an alert over the bus.
+ *
+ * @param alert kind of alert
+ * @param ... alert specific attributes
+ */
+ void (*alert)(bus_t *this, alert_t alert, ...);
+
+ /**
+ * Send a IKE_SA state change event to the bus.
+ *
+ * @param ike_sa IKE_SA which changes its state
+ * @param state new state IKE_SA changes to
+ */
+ void (*ike_state_change)(bus_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state);
+ /**
+ * Send a CHILD_SA state change event to the bus.
+ *
+ * @param child_sa CHILD_SA which changes its state
+ * @param state new state CHILD_SA changes to
+ */
+ void (*child_state_change)(bus_t *this, child_sa_t *child_sa,
+ child_sa_state_t state);
+ /**
+ * Message send/receive hook.
+ *
+ * @param message message to send/receive
+ * @param incoming TRUE for incoming messages, FALSE for outgoing
+ */
+ void (*message)(bus_t *this, message_t *message, bool incoming);
+
+ /**
+ * IKE_SA authorization hook.
+ *
+ * @param final TRUE if this is the final invocation
+ * @return TRUE to establish IKE_SA, FALSE to send AUTH_FAILED
+ */
+ bool (*authorize)(bus_t *this, bool final);
+
+ /**
+ * IKE_SA keymat hook.
+ *
+ * @param ike_sa IKE_SA this keymat belongs to
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @param rekey IKE_SA we are rekeying, if any
+ */
+ void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+ /**
+ * CHILD_SA keymat hook.
+ *
+ * @param child_sa CHILD_SA this keymat is used for
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ */
+ void (*child_keys)(bus_t *this, child_sa_t *child_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r);
+
+ /**
+ * IKE_SA up/down hook.
+ *
+ * @param ike_sa IKE_SA coming up/going down
+ * @param up TRUE for an up event, FALSE for a down event
+ */
+ void (*ike_updown)(bus_t *this, ike_sa_t *ike_sa, bool up);
+
+ /**
+ * IKE_SA rekeying hook.
+ *
+ * @param old rekeyed and obsolete IKE_SA
+ * @param new new IKE_SA replacing old
+ */
+ void (*ike_rekey)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
+ * CHILD_SA up/down hook.
+ *
+ * @param child_sa CHILD_SA coming up/going down
+ * @param up TRUE for an up event, FALSE for a down event
+ */
+ void (*child_updown)(bus_t *this, child_sa_t *child_sa, bool up);
+
+ /**
+ * CHILD_SA rekeying hook.
+ *
+ * @param old rekeyed and obsolete CHILD_SA
+ * @param new new CHILD_SA replacing old
+ */
+ void (*child_rekey)(bus_t *this, child_sa_t *old, child_sa_t *new);
+
+ /**
+ * Destroy the event bus.
+ */
+ void (*destroy) (bus_t *this);
+};
+
+/**
+ * Create the event bus which forwards events to its listeners.
+ *
+ * @return event bus instance
+ */
+bus_t *bus_create();
+
+#endif /** BUS_H_ @}*/
diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c
new file mode 100644
index 000000000..12587deaf
--- /dev/null
+++ b/src/libcharon/bus/listeners/file_logger.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006 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 <stdio.h>
+#include <string.h>
+
+#include "file_logger.h"
+
+
+typedef struct private_file_logger_t private_file_logger_t;
+
+/**
+ * Private data of a file_logger_t object
+ */
+struct private_file_logger_t {
+
+ /**
+ * Public data.
+ */
+ file_logger_t public;
+
+ /**
+ * output file
+ */
+ FILE *out;
+
+ /**
+ * Maximum level to log, for each group
+ */
+ level_t levels[DBG_MAX];
+};
+
+/**
+ * Implementation of bus_listener_t.log.
+ */
+static bool log_(private_file_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
+{
+ if (level <= this->levels[group])
+ {
+ char buffer[8192];
+ char *current = buffer, *next;
+
+ /* write in memory buffer first */
+ vsnprintf(buffer, sizeof(buffer), format, args);
+
+ /* prepend a prefix in front of every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ fprintf(this->out, "%.2d[%N] %s\n",
+ thread, debug_names, group, current);
+ current = next;
+ }
+ }
+ /* always stay registered */
+ return TRUE;
+}
+
+/**
+ * Implementation of file_logger_t.set_level.
+ */
+static void set_level(private_file_logger_t *this, debug_t group, level_t level)
+{
+ if (group < DBG_ANY)
+ {
+ this->levels[group] = level;
+ }
+ else
+ {
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->levels[group] = level;
+ }
+ }
+}
+
+/**
+ * Implementation of file_logger_t.destroy.
+ */
+static void destroy(private_file_logger_t *this)
+{
+ if (this->out != stdout && this->out != stderr)
+ {
+ fclose(this->out);
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+file_logger_t *file_logger_create(FILE *out)
+{
+ private_file_logger_t *this = malloc_thing(private_file_logger_t);
+
+ /* public functions */
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
+ this->public.set_level = (void(*)(file_logger_t*,debug_t,level_t))set_level;
+ this->public.destroy = (void(*)(file_logger_t*))destroy;
+
+ /* private variables */
+ this->out = out;
+ set_level(this, DBG_ANY, LEVEL_SILENT);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/bus/listeners/file_logger.h b/src/libcharon/bus/listeners/file_logger.h
new file mode 100644
index 000000000..bd443fdb8
--- /dev/null
+++ b/src/libcharon/bus/listeners/file_logger.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 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 file_logger file_logger
+ * @{ @ingroup listeners
+ */
+
+#ifndef FILE_LOGGER_H_
+#define FILE_LOGGER_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct file_logger_t file_logger_t;
+
+/**
+ * Logger to files which implements listener_t.
+ */
+struct file_logger_t {
+
+ /**
+ * Implements the listener_t interface.
+ */
+ listener_t listener;
+
+ /**
+ * Set the loglevel for a debug group.
+ *
+ * @param group debug group to set
+ * @param level max level to log (0..4)
+ */
+ void (*set_level) (file_logger_t *this, debug_t group, level_t level);
+
+ /**
+ * Destroys a file_logger_t object.
+ */
+ void (*destroy) (file_logger_t *this);
+};
+
+/**
+ * Constructor to create a file_logger_t object.
+ *
+ * @param out FILE to write to
+ * @return file_logger_t object
+ */
+file_logger_t *file_logger_create(FILE *out);
+
+#endif /** FILE_LOGGER_H_ @}*/
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
new file mode 100644
index 000000000..9a51a2ef4
--- /dev/null
+++ b/src/libcharon/bus/listeners/listener.h
@@ -0,0 +1,178 @@
+/*
+ * 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 listener listener
+ * @{ @ingroup listeners
+ */
+
+#ifndef LISTENER_H_
+#define LISTENER_H_
+
+typedef struct listener_t listener_t;
+
+#include <bus/bus.h>
+
+/**
+ * Listener interface, listens to events if registered to the bus.
+ */
+struct listener_t {
+
+ /**
+ * Log a debugging message.
+ *
+ * The implementing signal function returns TRUE to stay registered
+ * to the bus, or FALSE to unregister itself.
+ * Calling bus_t.log() inside of a registered listener is possible,
+ * but the bus does not invoke listeners recursively.
+ *
+ * @param group kind of the signal (up, down, rekeyed, ...)
+ * @param level verbosity level of the signal
+ * @param thread ID of the thread raised this signal
+ * @param ike_sa IKE_SA associated to the event
+ * @param format printf() style format string
+ * @param args vprintf() style va_list argument list
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*log)(listener_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t *ike_sa, char* format, va_list args);
+
+ /**
+ * Hook called if a critical alert is risen.
+ *
+ * @param ike_sa IKE_SA associated to the alert, if any
+ * @param alert kind of alert
+ * @param ... alert specific argument list
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*alert)(listener_t *this, ike_sa_t *ike_sa,
+ alert_t alert, va_list args);
+
+ /**
+ * Handle state changes in an IKE_SA.
+ *
+ * @param ike_sa IKE_SA which changes its state
+ * @param state new IKE_SA state this IKE_SA changes to
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_state_change)(listener_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state);
+
+ /**
+ * Handle state changes in a CHILD_SA.
+ *
+ * @param ike_sa IKE_SA containing the affected CHILD_SA
+ * @param child_sa CHILD_SA which changes its state
+ * @param state new CHILD_SA state this CHILD_SA changes to
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_state_change)(listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state);
+
+ /**
+ * Hook called for received/sent messages of an IKE_SA.
+ *
+ * @param ike_sa IKE_SA sending/receving a message
+ * @param message message object
+ * @param incoming TRUE for incoming messages, FALSE for outgoing
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*message)(listener_t *this, ike_sa_t *ike_sa, message_t *message,
+ bool incoming);
+
+ /**
+ * Hook called with IKE_SA key material.
+ *
+ * @param ike_sa IKE_SA this keymat belongs to
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @param rekey IKE_SA we are rekeying, if any
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+
+ /**
+ * Hook called with CHILD_SA key material.
+ *
+ * @param ike_sa IKE_SA the child sa belongs to
+ * @param child_sa CHILD_SA this keymat is used for
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
+
+ /**
+ * Hook called if an IKE_SA gets up or down.
+ *
+ * @param ike_sa IKE_SA coming up/going down
+ * @param up TRUE for an up event, FALSE for a down event
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_updown)(listener_t *this, ike_sa_t *ike_sa, bool up);
+
+ /**
+ * Hook called when an IKE_SA gets rekeyed.
+ *
+ * @param old rekeyed IKE_SA getting obsolete
+ * @param new new IKE_SA replacing old
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_rekey)(listener_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
+ * Hook called when a CHILD_SA gets up or down.
+ *
+ * @param ike_sa IKE_SA containing the handled CHILD_SA
+ * @param child_sa CHILD_SA coming up/going down
+ * @param up TRUE for an up event, FALSE for a down event
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_updown)(listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, bool up);
+
+ /**
+ * Hook called when an CHILD_SA gets rekeyed.
+ *
+ * @param ike_sa IKE_SA containing the rekeyed CHILD_SA
+ * @param old rekeyed CHILD_SA getting obsolete
+ * @param new new CHILD_SA replacing old
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_rekey)(listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *old, child_sa_t *new);
+
+ /**
+ * Hook called to invoke additional authorization rules.
+ *
+ * An authorization hook gets invoked several times: After each
+ * authentication round, the hook gets invoked with with final = FALSE.
+ * After authentication is complete and the peer configuration is selected,
+ * it is invoked again, but with final = TRUE.
+ *
+ * @param ike_sa IKE_SA to authorize
+ * @param final TRUE if this is the final hook invocation
+ * @param success set to TRUE to complete IKE_SA, FALSE abort
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*authorize)(listener_t *this, ike_sa_t *ike_sa,
+ bool final, bool *success);
+};
+
+#endif /** LISTENER_H_ @}*/
diff --git a/src/libcharon/bus/listeners/sys_logger.c b/src/libcharon/bus/listeners/sys_logger.c
new file mode 100644
index 000000000..11421ad05
--- /dev/null
+++ b/src/libcharon/bus/listeners/sys_logger.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2006 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 <stdio.h>
+#include <string.h>
+
+#include "sys_logger.h"
+
+
+typedef struct private_sys_logger_t private_sys_logger_t;
+
+/**
+ * Private data of a sys_logger_t object
+ */
+struct private_sys_logger_t {
+
+ /**
+ * Public data.
+ */
+ sys_logger_t public;
+
+ /**
+ * syslog facility to use
+ */
+ int facility;
+
+ /**
+ * Maximum level to log, for each group
+ */
+ level_t levels[DBG_MAX];
+};
+
+/**
+ * Implementation of listener_t.log.
+ */
+static bool log_(private_sys_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
+{
+ if (level <= this->levels[group])
+ {
+ char buffer[8192];
+ char *current = buffer, *next;
+
+ /* write in memory buffer first */
+ vsnprintf(buffer, sizeof(buffer), format, args);
+
+ /* do a syslog with every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(this->facility|LOG_INFO, "%.2d[%N] %s\n",
+ thread, debug_names, group, current);
+ current = next;
+ }
+ }
+ /* always stay registered */
+ return TRUE;
+}
+
+/**
+ * Implementation of sys_logger_t.set_level.
+ */
+static void set_level(private_sys_logger_t *this, debug_t group, level_t level)
+{
+ if (group < DBG_ANY)
+ {
+ this->levels[group] = level;
+ }
+ else
+ {
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->levels[group] = level;
+ }
+ }
+}
+
+/**
+ * Implementation of sys_logger_t.destroy.
+ */
+static void destroy(private_sys_logger_t *this)
+{
+ closelog();
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+sys_logger_t *sys_logger_create(int facility)
+{
+ private_sys_logger_t *this = malloc_thing(private_sys_logger_t);
+
+ /* public functions */
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
+ this->public.set_level = (void(*)(sys_logger_t*,debug_t,level_t))set_level;
+ this->public.destroy = (void(*)(sys_logger_t*))destroy;
+
+ /* private variables */
+ this->facility = facility;
+ set_level(this, DBG_ANY, LEVEL_SILENT);
+
+ return &this->public;
+}
diff --git a/src/libcharon/bus/listeners/sys_logger.h b/src/libcharon/bus/listeners/sys_logger.h
new file mode 100644
index 000000000..730890d68
--- /dev/null
+++ b/src/libcharon/bus/listeners/sys_logger.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2006 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 sys_logger sys_logger
+ * @{ @ingroup listeners
+ */
+
+#ifndef SYS_LOGGER_H_
+#define SYS_LOGGER_H_
+
+#include <syslog.h>
+
+#include <bus/listeners/listener.h>
+
+typedef struct sys_logger_t sys_logger_t;
+
+/**
+ * Logger for syslog which implements listener_t.
+ */
+struct sys_logger_t {
+
+ /**
+ * Implements the listener_t interface.
+ */
+ listener_t listener;
+
+ /**
+ * Set the loglevel for a debug group.
+ *
+ * @param group debug group to set
+ * @param level max level to log (0..4)
+ */
+ void (*set_level) (sys_logger_t *this, debug_t group, level_t level);
+
+ /**
+ * Destroys a sys_logger_t object.
+ */
+ void (*destroy) (sys_logger_t *this);
+};
+
+/**
+ * Constructor to create a sys_logger_t object.
+ *
+ * @param facility syslog facility to use
+ * @return sys_logger_t object
+ */
+sys_logger_t *sys_logger_create(int facility);
+
+#endif /** SYS_LOGGER_H_ @}*/
diff --git a/src/libcharon/config/auth_cfg.c b/src/libcharon/config/auth_cfg.c
new file mode 100644
index 000000000..94362c756
--- /dev/null
+++ b/src/libcharon/config/auth_cfg.c
@@ -0,0 +1,768 @@
+/*
+ * Copyright (C) 2007-2009 Martin Willi
+ * 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 "auth_cfg.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <credentials/certificates/certificate.h>
+
+ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
+ "RULE_IDENTITY",
+ "RULE_AUTH_CLASS",
+ "RULE_EAP_IDENTITY",
+ "RULE_EAP_TYPE",
+ "RULE_EAP_VENDOR",
+ "RULE_CA_CERT",
+ "RULE_IM_CERT",
+ "RULE_SUBJECT_CERT",
+ "RULE_CRL_VALIDATION",
+ "RULE_OCSP_VALIDATION",
+ "RULE_AC_GROUP",
+ "HELPER_IM_CERT",
+ "HELPER_SUBJECT_CERT",
+ "HELPER_IM_HASH_URL",
+ "HELPER_SUBJECT_HASH_URL",
+);
+
+typedef struct private_auth_cfg_t private_auth_cfg_t;
+
+/**
+ * private data of item_set
+ */
+struct private_auth_cfg_t {
+
+ /**
+ * public functions
+ */
+ auth_cfg_t public;
+
+ /**
+ * list of entry_t
+ */
+ linked_list_t *entries;
+};
+
+typedef struct entry_t entry_t;
+
+struct entry_t {
+ /** rule type */
+ auth_rule_t type;
+ /** associated value */
+ void *value;
+};
+
+/**
+ * enumerator for auth_cfg_t.create_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner enumerator from linked_list_t */
+ enumerator_t *inner;
+ /** current entry */
+ entry_t *current;
+} entry_enumerator_t;
+
+/**
+ * enumerate function for item_enumerator_t
+ */
+static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
+{
+ entry_t *entry;
+
+ if (this->inner->enumerate(this->inner, &entry))
+ {
+ this->current = entry;
+ *type = entry->type;
+ *value = entry->value;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for item_enumerator_t
+ */
+static void entry_enumerator_destroy(entry_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of auth_cfg_t.create_enumerator.
+ */
+static enumerator_t* create_enumerator(private_auth_cfg_t *this)
+{
+ entry_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(entry_enumerator_t);
+ enumerator->inner = this->entries->create_enumerator(this->entries);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)entry_enumerator_destroy;
+ enumerator->current = NULL;
+ return &enumerator->public;
+}
+
+/**
+ * Destroy the value associated with an entry
+ */
+static void destroy_entry_value(entry_t *entry)
+{
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ id->destroy(id);
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ cert->destroy(cert);
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ free(entry->value);
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ break;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.replace.
+ */
+static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
+ auth_rule_t type, ...)
+{
+ if (enumerator->current)
+ {
+ va_list args;
+
+ va_start(args, type);
+
+ destroy_entry_value(enumerator->current);
+ enumerator->current->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ enumerator->current->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.get.
+ */
+static void* get(private_auth_cfg_t *this, auth_rule_t type)
+{
+ enumerator_t *enumerator;
+ void *current_value, *best_value = NULL;
+ auth_rule_t current_type;
+ bool found = FALSE;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current_type, &current_value))
+ {
+ if (type == current_type)
+ {
+ if (type == AUTH_RULE_CRL_VALIDATION ||
+ type == AUTH_RULE_OCSP_VALIDATION)
+ { /* for CRL/OCSP validation, always get() the highest value */
+ if (!found || current_value > best_value)
+ {
+ best_value = current_value;
+ }
+ found = TRUE;
+ continue;
+ }
+ best_value = current_value;
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ return best_value;
+ }
+ switch (type)
+ {
+ /* use some sane defaults if we don't find an entry */
+ case AUTH_RULE_AUTH_CLASS:
+ return (void*)AUTH_CLASS_ANY;
+ case AUTH_RULE_EAP_TYPE:
+ return (void*)EAP_NAK;
+ case AUTH_RULE_EAP_VENDOR:
+ return (void*)0;
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ return (void*)VALIDATION_FAILED;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.add.
+ */
+static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
+{
+ entry_t *entry = malloc_thing(entry_t);
+ va_list args;
+
+ va_start(args, type);
+ entry->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ entry->value = (void*)(uintptr_t)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ entry->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ this->entries->insert_last(this->entries, entry);
+}
+
+/**
+ * Implementation of auth_cfg_t.complies.
+ */
+static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
+ bool log_error)
+{
+ enumerator_t *e1, *e2;
+ bool success = TRUE;
+ auth_rule_t t1, t2;
+ void *value;
+
+ e1 = constraints->create_enumerator(constraints);
+ while (e1->enumerate(e1, &t1, &value))
+ {
+ switch (t1)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+
+ success = FALSE;
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &c2))
+ {
+ if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
+ c1->equals(c1, c2))
+ {
+ success = TRUE;
+ }
+ }
+ e2->destroy(e2);
+ if (!success && log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated by CA '%Y'.", c1->get_subject(c1));
+ }
+ break;
+ }
+ case AUTH_RULE_SUBJECT_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+ c2 = get(this, AUTH_RULE_SUBJECT_CERT);
+ if (!c2 || !c1->equals(c1, c2))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated with peer cert '%Y'.",
+ c1->get_subject(c1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ cert_validation_t validated, required;
+
+ required = (uintptr_t)value;
+ validated = (uintptr_t)get(this, t1);
+ switch (required)
+ {
+ case VALIDATION_FAILED:
+ /* no constraint */
+ break;
+ case VALIDATION_SKIPPED:
+ if (validated == VALIDATION_SKIPPED)
+ {
+ break;
+ }
+ /* FALL */
+ case VALIDATION_GOOD:
+ if (validated == VALIDATION_GOOD)
+ {
+ break;
+ }
+ /* FALL */
+ default:
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %N is %N, "
+ "but requires at least %N", auth_rule_names,
+ t1, cert_validation_names, validated,
+ cert_validation_names, required);
+ }
+ break;
+ }
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)value;
+ id2 = get(this, t1);
+ if (!id2 || !id2->matches(id2, id1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
+ " required ", t1 == AUTH_RULE_IDENTITY ? "" :
+ "EAP ", id1);
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ {
+ if ((uintptr_t)value != AUTH_CLASS_ANY &&
+ (uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N authentication, "
+ "but %N was used", auth_class_names, (uintptr_t)value,
+ auth_class_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_TYPE:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N, "
+ "but %N was used", eap_type_names, (uintptr_t)value,
+ eap_type_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
+ "but %d was used", (uintptr_t)value,
+ (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_AC_GROUP:
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check %N not implemented!",
+ auth_rule_names, t1);
+ }
+ break;
+ }
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* skip helpers */
+ continue;
+ }
+ if (!success)
+ {
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return success;
+}
+
+/**
+ * Implementation of auth_cfg_t.merge.
+ */
+static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
+{
+ if (!other)
+ { /* nothing to merge */
+ return;
+ }
+ if (copy)
+ {
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = create_enumerator(other);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)value;
+
+ add(this, type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ add(this, type, (uintptr_t)value);
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)value;
+
+ add(this, type, id->clone(id));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ add(this, type, strdup((char*)value));
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ entry_t *entry;
+
+ while (other->entries->remove_first(other->entries,
+ (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_last(this->entries, entry);
+ }
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.equals.
+ */
+static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
+{
+ enumerator_t *e1, *e2;
+ entry_t *i1, *i2;
+ bool equal = TRUE, found;
+
+ if (this->entries->get_count(this->entries) !=
+ other->entries->get_count(other->entries))
+ {
+ return FALSE;
+ }
+ e1 = this->entries->create_enumerator(this->entries);
+ while (e1->enumerate(e1, &i1))
+ {
+ found = FALSE;
+ e2 = other->entries->create_enumerator(other->entries);
+ while (e2->enumerate(e2, &i2))
+ {
+ if (i1->type == i2->type)
+ {
+ switch (i1->type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ if (i1->value == i2->value)
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)i1->value;
+ c2 = (certificate_t*)i2->value;
+
+ if (c1->equals(c1, c2))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)i1->value;
+ id2 = (identification_t*)i2->value;
+
+ if (id1->equals(id1, id2))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ if (streq(i1->value, i2->value))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (!found)
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return equal;
+}
+
+/**
+ * Implementation of auth_cfg_t.purge
+ */
+static void purge(private_auth_cfg_t *this, bool keep_ca)
+{
+ entry_t *entry;
+ linked_list_t *cas;
+
+ cas = linked_list_create();
+ while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
+ {
+ if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
+ {
+ cas->insert_first(cas, entry);
+ }
+ else
+ {
+ destroy_entry_value(entry);
+ free(entry);
+ }
+ }
+ while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_first(this->entries, entry);
+ }
+ cas->destroy(cas);
+}
+
+/**
+ * Implementation of auth_cfg_t.clone
+ */
+static auth_cfg_t* clone_(private_auth_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *clone;
+ entry_t *entry;
+
+ clone = auth_cfg_create();
+ enumerator = this->entries->create_enumerator(this->entries);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ clone->add(clone, entry->type, id->clone(id));
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ clone->add(clone, entry->type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ clone->add(clone, entry->type, strdup(entry->value));
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ clone->add(clone, entry->type, (uintptr_t)entry->value);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return clone;
+}
+
+/**
+ * Implementation of auth_cfg_t.destroy
+ */
+static void destroy(private_auth_cfg_t *this)
+{
+ purge(this, FALSE);
+ this->entries->destroy(this->entries);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_t *auth_cfg_create()
+{
+ private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
+
+ this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
+ this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
+ this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
+ this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
+ this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
+ this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
+ this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
+ this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
+ this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
+ this->public.destroy = (void(*)(auth_cfg_t*))destroy;
+
+ this->entries = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/config/auth_cfg.h b/src/libcharon/config/auth_cfg.h
new file mode 100644
index 000000000..5e6215a4a
--- /dev/null
+++ b/src/libcharon/config/auth_cfg.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007-2009 Martin Willi
+ * 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 auth_cfg auth_cfg
+ * @{ @ingroup config
+ */
+
+#ifndef AUTH_CFG_H_
+#define AUTH_CFG_H_
+
+#include <utils/enumerator.h>
+
+typedef struct auth_cfg_t auth_cfg_t;
+typedef enum auth_rule_t auth_rule_t;
+
+/**
+ * Authentication config to use during authentication process.
+ *
+ * Each authentication config contains a set of rules. These rule-sets are used
+ * in two ways:
+ * - For configs specifying local authentication behavior, the rules define
+ * which authentication method in which way.
+ * - For configs specifying remote peer authentication, the rules define
+ * constraints the peer has to fullfill.
+ *
+ * Additionally to the rules, there is a set of helper items. These are used
+ * to transport credentials during the authentication process.
+ */
+enum auth_rule_t {
+
+ /** identity to use for IKEv2 authentication exchange, identification_t* */
+ AUTH_RULE_IDENTITY,
+ /** authentication class, auth_class_t */
+ AUTH_RULE_AUTH_CLASS,
+ /** EAP identity to use within EAP-Identity exchange, identification_t* */
+ AUTH_RULE_EAP_IDENTITY,
+ /** EAP type to propose for peer authentication, eap_type_t */
+ AUTH_RULE_EAP_TYPE,
+ /** EAP vendor for vendor specific type, u_int32_t */
+ AUTH_RULE_EAP_VENDOR,
+ /** certificate authority, certificate_t* */
+ AUTH_RULE_CA_CERT,
+ /** intermediate certificate in trustchain, certificate_t* */
+ AUTH_RULE_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_RULE_SUBJECT_CERT,
+ /** result of a CRL validation, cert_validation_t */
+ AUTH_RULE_CRL_VALIDATION,
+ /** result of a OCSP validation, cert_validation_t */
+ AUTH_RULE_OCSP_VALIDATION,
+ /** subject is in attribute certificate group, identification_t* */
+ AUTH_RULE_AC_GROUP,
+
+ /** intermediate certificate, certificate_t* */
+ AUTH_HELPER_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_HELPER_SUBJECT_CERT,
+ /** Hash and URL of a intermediate certificate, char* */
+ AUTH_HELPER_IM_HASH_URL,
+ /** Hash and URL of a end-entity certificate, char* */
+ AUTH_HELPER_SUBJECT_HASH_URL,
+};
+
+/**
+ * enum name for auth_rule_t.
+ */
+extern enum_name_t *auth_rule_names;
+
+/**
+ * Authentication/Authorization round.
+ *
+ * RFC4739 defines multiple authentication rounds. This class defines such
+ * a round from a configuration perspective, either for the local or the remote
+ * peer. Local config are called "rulesets", as they define how we authenticate.
+ * Remote peer configs are called "constraits", they define what is needed to
+ * complete the authentication round successfully.
+ *
+ * @verbatim
+
+ [Repeat for each configuration]
+ +--------------------------------------------------+
+ | |
+ | |
+ | +----------+ IKE_AUTH +--------- + |
+ | | config | -----------> | | |
+ | | ruleset | | | |
+ | +----------+ [ <----------- ] | | |
+ | [ optional EAP ] | Peer | |
+ | +----------+ [ -----------> ] | | |
+ | | config | | | |
+ | | constr. | <----------- | | |
+ | +----------+ IKE_AUTH +--------- + |
+ | |
+ | |
+ +--------------------------------------------------+
+
+ @endverbatim
+ *
+ * Values for each items are either pointers (casted to void*) or short
+ * integers (use uintptr_t cast).
+ */
+struct auth_cfg_t {
+
+ /**
+ * Add an rule to the set.
+ *
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*add)(auth_cfg_t *this, auth_rule_t rule, ...);
+
+ /**
+ * Get an rule value.
+ *
+ * @param rule rule type
+ * @return bool if item has been found
+ */
+ void* (*get)(auth_cfg_t *this, auth_rule_t rule);
+
+ /**
+ * Create an enumerator over added rules.
+ *
+ * @return enumerator over (auth_rule_t, union{void*,uintpr_t})
+ */
+ enumerator_t* (*create_enumerator)(auth_cfg_t *this);
+
+ /**
+ * Replace an rule at enumerator position.
+ *
+ * @param pos enumerator position position
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*replace)(auth_cfg_t *this, enumerator_t *pos,
+ auth_rule_t rule, ...);
+
+ /**
+ * Check if a used config fulfills a set of configured constraints.
+ *
+ * @param constraints required authorization rules
+ * @param log_error wheter to log compliance errors
+ * @return TRUE if this complies with constraints
+ */
+ bool (*complies)(auth_cfg_t *this, auth_cfg_t *constraints, bool log_error);
+
+ /**
+ * Merge items from other into this.
+ *
+ * @param other items to read for merge
+ * @param copy TRUE to copy items, FALSE to move them
+ */
+ void (*merge)(auth_cfg_t *this, auth_cfg_t *other, bool copy);
+
+ /**
+ * Purge all rules in a config.
+ *
+ * @param keep_ca wheter to keep AUTH_RULE_CA_CERT entries
+ */
+ void (*purge)(auth_cfg_t *this, bool keep_ca);
+
+ /**
+ * Check two configs for equality.
+ *
+ * @param other other config to compaire against this
+ * @return TRUE if auth infos identical
+ */
+ bool (*equals)(auth_cfg_t *this, auth_cfg_t *other);
+
+ /**
+ * Clone a authentication config, including all rules.
+ *
+ * @return cloned configuration
+ */
+ auth_cfg_t* (*clone)(auth_cfg_t *this);
+
+ /**
+ * Destroy a config with all associated rules/values.
+ */
+ void (*destroy)(auth_cfg_t *this);
+};
+
+/**
+ * Create a authentication config.
+ */
+auth_cfg_t *auth_cfg_create();
+
+#endif /** AUTH_CFG_H_ @}*/
diff --git a/src/libcharon/config/backend.h b/src/libcharon/config/backend.h
new file mode 100644
index 000000000..458abc37f
--- /dev/null
+++ b/src/libcharon/config/backend.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007-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 backend backend
+ * @{ @ingroup config
+ */
+
+#ifndef BACKEND_H_
+#define BACKEND_H_
+
+typedef struct backend_t backend_t;
+
+#include <library.h>
+#include <config/ike_cfg.h>
+#include <config/peer_cfg.h>
+#include <utils/linked_list.h>
+
+/**
+ * The interface for a configuration backend.
+ *
+ * A configuration backend is loaded into the backend_manager. It does the actual
+ * configuration lookup for the method it implements. See backend_manager_t for
+ * more information.
+ */
+struct backend_t {
+
+ /**
+ * Create an enumerator over all IKE configs matching two hosts.
+ *
+ * Hosts may be NULL to get all.
+ *
+ * There is no requirement for the backend to filter the configurations
+ * using the supplied hosts; but it may do so if it increases lookup times
+ * (e.g. include hosts in SQL query).
+ *
+ * @param me address of local host
+ * @param other address of remote host
+ * @return enumerator over ike_cfg_t's
+ */
+ enumerator_t* (*create_ike_cfg_enumerator)(backend_t *this,
+ host_t *me, host_t *other);
+ /**
+ * Create an enumerator over all peer configs matching two identities.
+ *
+ * IDs may be NULL to get all.
+ *
+ * As configurations are looked up in the first authentication round (when
+ * multiple authentication), the backend implementation should compare
+ * the identities to the first auth_cfgs only.
+ * There is no requirement for the backend to filter the configurations
+ * using the supplied identities; but it may do so if it increases lookup
+ * times (e.g. include hosts in SQL query).
+ *
+ * @param me identity of ourself
+ * @param other identity of remote host
+ * @return enumerator over peer_cfg_t
+ */
+ enumerator_t* (*create_peer_cfg_enumerator)(backend_t *this,
+ identification_t *me,
+ identification_t *other);
+ /**
+ * Get a peer_cfg identified by it's name, or a name of its children.
+ *
+ * @param name name of peer/child cfg
+ * @return matching peer_config, or NULL if none found
+ */
+ peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name);
+};
+
+#endif /** BACKEND_H_ @}*/
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c
new file mode 100644
index 000000000..90ef58563
--- /dev/null
+++ b/src/libcharon/config/backend_manager.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2007-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 "backend_manager.h"
+
+#include <sys/types.h>
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+
+typedef struct private_backend_manager_t private_backend_manager_t;
+
+/**
+ * Private data of an backend_manager_t object.
+ */
+struct private_backend_manager_t {
+
+ /**
+ * Public part of backend_manager_t object.
+ */
+ backend_manager_t public;
+
+ /**
+ * list of registered backends
+ */
+ linked_list_t *backends;
+
+ /**
+ * rwlock for backends
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * match of an ike_cfg
+ */
+typedef enum ike_cfg_match_t {
+ MATCH_NONE = 0x00,
+ MATCH_ANY = 0x01,
+ MATCH_ME = 0x04,
+ MATCH_OTHER = 0x08,
+} ike_cfg_match_t;
+
+/**
+ * data to pass nested IKE enumerator
+ */
+typedef struct {
+ private_backend_manager_t *this;
+ host_t *me;
+ host_t *other;
+} ike_data_t;
+
+/**
+ * inner enumerator constructor for IKE cfgs
+ */
+static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data)
+{
+ return backend->create_ike_cfg_enumerator(backend, data->me, data->other);
+}
+
+/**
+ * get a match of a candidate ike_cfg for two hosts
+ */
+static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
+{
+ host_t *me_cand, *other_cand;
+ ike_cfg_match_t match = MATCH_NONE;
+
+ if (me)
+ {
+ me_cand = host_create_from_dns(cand->get_my_addr(cand),
+ me->get_family(me), 0);
+ if (!me_cand)
+ {
+ return MATCH_NONE;
+ }
+ if (me_cand->ip_equals(me_cand, me))
+ {
+ match += MATCH_ME;
+ }
+ else if (me_cand->is_anyaddr(me_cand))
+ {
+ match += MATCH_ANY;
+ }
+ me_cand->destroy(me_cand);
+ }
+ else
+ {
+ match += MATCH_ANY;
+ }
+
+ if (other)
+ {
+ other_cand = host_create_from_dns(cand->get_other_addr(cand),
+ other->get_family(other), 0);
+ if (!other_cand)
+ {
+ return MATCH_NONE;
+ }
+ if (other_cand->ip_equals(other_cand, other))
+ {
+ match += MATCH_OTHER;
+ }
+ else if (other_cand->is_anyaddr(other_cand))
+ {
+ match += MATCH_ANY;
+ }
+ other_cand->destroy(other_cand);
+ }
+ else
+ {
+ match += MATCH_ANY;
+ }
+ return match;
+}
+
+/**
+ * implements backend_manager_t.get_ike_cfg.
+ */
+static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
+ host_t *me, host_t *other)
+{
+ ike_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+ ike_cfg_match_t match, best = MATCH_ANY;
+ ike_data_t *data;
+
+ data = malloc_thing(ike_data_t);
+ data->this = this;
+ data->me = me;
+ data->other = other;
+
+ DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other);
+
+ this->lock->read_lock(this->lock);
+ enumerator = enumerator_create_nested(
+ this->backends->create_enumerator(this->backends),
+ (void*)ike_enum_create, data, (void*)free);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ match = get_ike_match(current, me, other);
+
+ if (match)
+ {
+ DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
+ current->get_my_addr(current),
+ current->get_other_addr(current), match);
+ if (match > best)
+ {
+ DESTROY_IF(found);
+ found = current;
+ found->get_ref(found);
+ best = match;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ if (found)
+ {
+ DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d",
+ found->get_my_addr(found), found->get_other_addr(found), best);
+ }
+ return found;
+}
+
+/**
+ * Get the best ID match in one of the configs auth_cfg
+ */
+static id_match_t get_peer_match(identification_t *id,
+ peer_cfg_t *cfg, bool local)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ identification_t *candidate;
+ id_match_t match = ID_MATCH_NONE;
+
+ if (!id)
+ {
+ return ID_MATCH_ANY;
+ }
+
+ /* compare first auth config only */
+ enumerator = cfg->create_auth_cfg_enumerator(cfg, local);
+ if (enumerator->enumerate(enumerator, &auth))
+ {
+ candidate = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (candidate)
+ {
+ match = id->matches(id, candidate);
+ /* match vice-versa, as the proposed IDr might be ANY */
+ if (!match)
+ {
+ match = candidate->matches(candidate, id);
+ }
+ }
+ else
+ {
+ match = ID_MATCH_ANY;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return match;
+}
+
+/**
+ * data to pass nested peer enumerator
+ */
+typedef struct {
+ rwlock_t *lock;
+ identification_t *me;
+ identification_t *other;
+} peer_data_t;
+
+/**
+ * list element to help sorting
+ */
+typedef struct {
+ id_match_t match_peer;
+ ike_cfg_match_t match_ike;
+ peer_cfg_t *cfg;
+} match_entry_t;
+
+/**
+ * inner enumerator constructor for peer cfgs
+ */
+static enumerator_t *peer_enum_create(backend_t *backend, peer_data_t *data)
+{
+ return backend->create_peer_cfg_enumerator(backend, data->me, data->other);
+}
+
+/**
+ * unlock/cleanup peer enumerator
+ */
+static void peer_enum_destroy(peer_data_t *data)
+{
+ data->lock->unlock(data->lock);
+ free(data);
+}
+
+/**
+ * convert enumerator value from match_entry to config
+ */
+static bool peer_enum_filter(linked_list_t *configs,
+ match_entry_t **in, peer_cfg_t **out)
+{
+ *out = (*in)->cfg;
+ return TRUE;
+}
+
+/**
+ * Clean up temporary config list
+ */
+static void peer_enum_filter_destroy(linked_list_t *configs)
+{
+ match_entry_t *entry;
+
+ while (configs->remove_last(configs, (void**)&entry) == SUCCESS)
+ {
+ entry->cfg->destroy(entry->cfg);
+ free(entry);
+ }
+ configs->destroy(configs);
+}
+
+/**
+ * Insert entry into match-sorted list, using helper
+ */
+static void insert_sorted(match_entry_t *entry, linked_list_t *list,
+ linked_list_t *helper)
+{
+ match_entry_t *current;
+
+ while (list->remove_first(list, (void**)&current) == SUCCESS)
+ {
+ helper->insert_last(helper, current);
+ }
+ while (helper->remove_first(helper, (void**)&current) == SUCCESS)
+ {
+ if (entry && (
+ (entry->match_ike > current->match_ike &&
+ entry->match_peer >= current->match_peer) ||
+ (entry->match_ike >= current->match_ike &&
+ entry->match_peer > current->match_peer)))
+ {
+ list->insert_last(list, entry);
+ entry = NULL;
+ }
+ list->insert_last(list, current);
+ }
+ if (entry)
+ {
+ list->insert_last(list, entry);
+ }
+}
+
+/**
+ * Implements backend_manager_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this,
+ host_t *me, host_t *other, identification_t *my_id,
+ identification_t *other_id)
+{
+ enumerator_t *enumerator;
+ peer_data_t *data;
+ peer_cfg_t *cfg;
+ linked_list_t *configs, *helper;
+
+ data = malloc_thing(peer_data_t);
+ data->lock = this->lock;
+ data->me = my_id;
+ data->other = other_id;
+
+ /* create a sorted list with all matches */
+ this->lock->read_lock(this->lock);
+ enumerator = enumerator_create_nested(
+ this->backends->create_enumerator(this->backends),
+ (void*)peer_enum_create, data, (void*)peer_enum_destroy);
+
+ if (!me && !other && !my_id && !other_id)
+ { /* shortcut if we are doing a "listall" */
+ return enumerator;
+ }
+
+ DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]",
+ me, my_id, other, other_id);
+
+ configs = linked_list_create();
+ /* only once allocated helper list for sorting */
+ helper = linked_list_create();
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ id_match_t match_peer_me, match_peer_other;
+ ike_cfg_match_t match_ike;
+ match_entry_t *entry;
+
+ match_peer_me = get_peer_match(my_id, cfg, TRUE);
+ match_peer_other = get_peer_match(other_id, cfg, FALSE);
+ match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other);
+
+ if (match_peer_me && match_peer_other && match_ike)
+ {
+ DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)",
+ cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike);
+
+ entry = malloc_thing(match_entry_t);
+ entry->match_peer = match_peer_me + match_peer_other;
+ entry->match_ike = match_ike;
+ entry->cfg = cfg->get_ref(cfg);
+ insert_sorted(entry, configs, helper);
+ }
+ }
+ enumerator->destroy(enumerator);
+ helper->destroy(helper);
+
+ return enumerator_create_filter(configs->create_enumerator(configs),
+ (void*)peer_enum_filter, configs,
+ (void*)peer_enum_filter_destroy);
+}
+
+/**
+ * implements backend_manager_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name)
+{
+ backend_t *backend;
+ peer_cfg_t *config = NULL;
+ enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->backends->create_enumerator(this->backends);
+ while (config == NULL && enumerator->enumerate(enumerator, (void**)&backend))
+ {
+ config = backend->get_peer_cfg_by_name(backend, name);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return config;
+}
+
+/**
+ * Implementation of backend_manager_t.remove_backend.
+ */
+static void remove_backend(private_backend_manager_t *this, backend_t *backend)
+{
+ this->lock->write_lock(this->lock);
+ this->backends->remove(this->backends, backend, NULL);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of backend_manager_t.add_backend.
+ */
+static void add_backend(private_backend_manager_t *this, backend_t *backend)
+{
+ this->lock->write_lock(this->lock);
+ this->backends->insert_last(this->backends, backend);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of backend_manager_t.destroy.
+ */
+static void destroy(private_backend_manager_t *this)
+{
+ this->backends->destroy(this->backends);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * Described in header-file
+ */
+backend_manager_t *backend_manager_create()
+{
+ private_backend_manager_t *this = malloc_thing(private_backend_manager_t);
+
+ this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg;
+ this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name;
+ this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_t*))create_peer_cfg_enumerator;
+ this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend;
+ this->public.remove_backend = (void(*)(backend_manager_t*, backend_t *backend))remove_backend;
+ this->public.destroy = (void (*)(backend_manager_t*))destroy;
+
+ this->backends = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/config/backend_manager.h b/src/libcharon/config/backend_manager.h
new file mode 100644
index 000000000..5b394f791
--- /dev/null
+++ b/src/libcharon/config/backend_manager.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup backend_manager backend_manager
+ * @{ @ingroup config
+ */
+
+#ifndef BACKEND_MANAGER_H_
+#define BACKEND_MANAGER_H_
+
+typedef struct backend_manager_t backend_manager_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <config/ike_cfg.h>
+#include <config/peer_cfg.h>
+#include <config/backend.h>
+
+
+/**
+ * A loader and multiplexer to use multiple backends.
+ *
+ * Charon allows the use of multiple configuration backends simultaneously. To
+ * access all this backends by a single call, this class wraps multiple
+ * backends behind a single object.
+ * @verbatim
+
+ +---------+ +-----------+ +--------------+ |
+ | | | | +--------------+ | |
+ | daemon |----->| backend_- | +--------------+ |-+ <==|==> IPC
+ | core | | manager |---->| backends |-+ |
+ | |----->| | +--------------+ |
+ | | | | |
+ +---------+ +-----------+ |
+
+ @endverbatim
+ */
+struct backend_manager_t {
+
+ /**
+ * Get an ike_config identified by two hosts.
+ *
+ * @param my_host address of own host
+ * @param other_host address of remote host
+ * @return matching ike_config, or NULL if none found
+ */
+ ike_cfg_t* (*get_ike_cfg)(backend_manager_t *this,
+ host_t *my_host, host_t *other_host);
+
+ /**
+ * Get a peer_config identified by it's name.
+ *
+ * @param name name of the peer_config
+ * @return matching peer_config, or NULL if none found
+ */
+ peer_cfg_t* (*get_peer_cfg_by_name)(backend_manager_t *this, char *name);
+
+ /**
+ * Create an enumerator over all matching peer configs.
+ *
+ * Pass NULL as parameters to match any. The enumerator enumerates over
+ * peer_cfgs, ordered by priority (best match first).
+ *
+ * @param me local address
+ * @param other remote address
+ * @param my_id IDr in first authentication round
+ * @param other_id IDi in first authentication round
+ * @return enumerator over peer_cfg_t
+ */
+ enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this,
+ host_t *me, host_t *other, identification_t *my_id,
+ identification_t *other_id);
+ /**
+ * Register a backend on the manager.
+ *
+ * @param backend backend to register
+ */
+ void (*add_backend)(backend_manager_t *this, backend_t *backend);
+
+ /**
+ * Unregister a backend.
+ *
+ * @param backend backend to unregister
+ */
+ void (*remove_backend)(backend_manager_t *this, backend_t *backend);
+
+ /**
+ * Destroys a backend_manager_t object.
+ */
+ void (*destroy) (backend_manager_t *this);
+};
+
+/**
+ * Create an instance of the backend manager
+ *
+ * @return backend_manager instance
+ */
+backend_manager_t* backend_manager_create(void);
+
+#endif /** BACKEND_MANAGER_H_ @}*/
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
new file mode 100644
index 000000000..8410b3fe5
--- /dev/null
+++ b/src/libcharon/config/child_cfg.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "child_cfg.h"
+
+#include <daemon.h>
+
+ENUM(action_names, ACTION_NONE, ACTION_RESTART,
+ "clear",
+ "hold",
+ "restart",
+);
+
+ENUM_BEGIN(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_NONE,
+ "IPCOMP_NONE");
+ENUM_NEXT(ipcomp_transform_names, IPCOMP_OUI, IPCOMP_LZJH, IPCOMP_NONE,
+ "IPCOMP_OUI",
+ "IPCOMP_DEFLATE",
+ "IPCOMP_LZS",
+ "IPCOMP_LZJH");
+ENUM_END(ipcomp_transform_names, IPCOMP_LZJH);
+
+typedef struct private_child_cfg_t private_child_cfg_t;
+
+/**
+ * Private data of an child_cfg_t object
+ */
+struct private_child_cfg_t {
+
+ /**
+ * Public part
+ */
+ child_cfg_t public;
+
+ /**
+ * Number of references hold by others to this child_cfg
+ */
+ refcount_t refcount;
+
+ /**
+ * Name of the child_cfg, used to query it
+ */
+ char *name;
+
+ /**
+ * list for all proposals
+ */
+ linked_list_t *proposals;
+
+ /**
+ * list for traffic selectors for my site
+ */
+ linked_list_t *my_ts;
+
+ /**
+ * list for traffic selectors for others site
+ */
+ linked_list_t *other_ts;
+
+ /**
+ * updown script
+ */
+ char *updown;
+
+ /**
+ * allow host access
+ */
+ bool hostaccess;
+
+ /**
+ * Mode to propose for a initiated CHILD: tunnel/transport
+ */
+ ipsec_mode_t mode;
+
+ /**
+ * action to take on DPD
+ */
+ action_t dpd_action;
+
+ /**
+ * action to take on CHILD_SA close
+ */
+ action_t close_action;
+
+ /**
+ * CHILD_SA lifetime config
+ */
+ lifetime_cfg_t lifetime;
+
+ /**
+ * enable IPComp
+ */
+ bool use_ipcomp;
+
+ /**
+ * Inactivity timeout
+ */
+ u_int32_t inactivity;
+
+ /**
+ * set up IPsec transport SA in MIPv6 proxy mode
+ */
+ bool proxy_mode;
+
+ /**
+ * enable installation and removal of kernel IPsec policies
+ */
+ bool install_policy;
+};
+
+/**
+ * Implementation of child_cfg_t.get_name.
+ */
+static char *get_name(private_child_cfg_t *this)
+{
+ return this->name;
+}
+
+/**
+ * Implementation of child_cfg_t.add_proposal.
+ */
+static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
+{
+ this->proposals->insert_last(this->proposals, proposal);
+}
+
+/**
+ * Implementation of child_cfg_t.get_proposals.
+ */
+static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
+{
+ enumerator_t *enumerator;
+ proposal_t *current;
+ linked_list_t *proposals = linked_list_create();
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current = current->clone(current);
+ if (strip_dh)
+ {
+ current->strip_dh(current);
+ }
+ proposals->insert_last(proposals, current);
+ }
+ enumerator->destroy(enumerator);
+
+ return proposals;
+}
+
+/**
+ * Implementation of child_cfg_t.select_proposal.
+ */
+static proposal_t* select_proposal(private_child_cfg_t*this,
+ linked_list_t *proposals, bool strip_dh,
+ bool private)
+{
+ enumerator_t *stored_enum, *supplied_enum;
+ proposal_t *stored, *supplied, *selected = NULL;
+
+ stored_enum = this->proposals->create_enumerator(this->proposals);
+ supplied_enum = proposals->create_enumerator(proposals);
+
+ /* compare all stored proposals with all supplied. Stored ones are preferred. */
+ while (stored_enum->enumerate(stored_enum, &stored))
+ {
+ stored = stored->clone(stored);
+ while (supplied_enum->enumerate(supplied_enum, &supplied))
+ {
+ if (strip_dh)
+ {
+ stored->strip_dh(stored);
+ }
+ selected = stored->select(stored, supplied, private);
+ if (selected)
+ {
+ DBG2(DBG_CFG, "received proposals: %#P", proposals);
+ DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
+ DBG2(DBG_CFG, "selected proposal: %P", selected);
+ break;
+ }
+ }
+ stored->destroy(stored);
+ if (selected)
+ {
+ break;
+ }
+ supplied_enum->destroy(supplied_enum);
+ supplied_enum = proposals->create_enumerator(proposals);
+ }
+ stored_enum->destroy(stored_enum);
+ supplied_enum->destroy(supplied_enum);
+ if (selected == NULL)
+ {
+ DBG1(DBG_CFG, "received proposals: %#P", proposals);
+ DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
+ }
+ return selected;
+}
+
+/**
+ * Implementation of child_cfg_t.add_traffic_selector.
+ */
+static void add_traffic_selector(private_child_cfg_t *this, bool local,
+ traffic_selector_t *ts)
+{
+ if (local)
+ {
+ this->my_ts->insert_last(this->my_ts, ts);
+ }
+ else
+ {
+ this->other_ts->insert_last(this->other_ts, ts);
+ }
+}
+
+/**
+ * Implementation of child_cfg_t.get_traffic_selectors.
+ */
+static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
+ linked_list_t *supplied,
+ host_t *host)
+{
+ enumerator_t *e1, *e2;
+ traffic_selector_t *ts1, *ts2, *selected;
+ linked_list_t *result = linked_list_create();
+
+ if (local)
+ {
+ e1 = this->my_ts->create_enumerator(this->my_ts);
+ }
+ else
+ {
+ e1 = this->other_ts->create_enumerator(this->other_ts);
+ }
+
+ /* no list supplied, just fetch the stored traffic selectors */
+ if (supplied == NULL)
+ {
+ DBG2(DBG_CFG, "proposing traffic selectors for %s:",
+ local ? "us" : "other");
+ while (e1->enumerate(e1, &ts1))
+ {
+ /* we make a copy of the TS, this allows us to update dynamic TS' */
+ selected = ts1->clone(ts1);
+ if (host)
+ {
+ selected->set_address(selected, host);
+ }
+ DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1);
+ result->insert_last(result, selected);
+ }
+ e1->destroy(e1);
+ }
+ else
+ {
+ DBG2(DBG_CFG, "selecting traffic selectors for %s:",
+ local ? "us" : "other");
+ e2 = supplied->create_enumerator(supplied);
+ /* iterate over all stored selectors */
+ while (e1->enumerate(e1, &ts1))
+ {
+ /* we make a copy of the TS, as we have to update dynamic TS' */
+ ts1 = ts1->clone(ts1);
+ if (host)
+ {
+ ts1->set_address(ts1, host);
+ }
+
+ /* iterate over all supplied traffic selectors */
+ while (e2->enumerate(e2, &ts2))
+ {
+ selected = ts1->get_subset(ts1, ts2);
+ if (selected)
+ {
+ DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
+ ts1, ts2, selected);
+ result->insert_last(result, selected);
+ }
+ else
+ {
+ DBG2(DBG_CFG, " config: %R, received: %R => no match",
+ ts1, ts2);
+ }
+ }
+ e2->destroy(e2);
+ e2 = supplied->create_enumerator(supplied);
+ ts1->destroy(ts1);
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+ }
+
+ /* remove any redundant traffic selectors in the list */
+ e1 = result->create_enumerator(result);
+ e2 = result->create_enumerator(result);
+ while (e1->enumerate(e1, &ts1))
+ {
+ while (e2->enumerate(e2, &ts2))
+ {
+ if (ts1 != ts2)
+ {
+ if (ts2->is_contained_in(ts2, ts1))
+ {
+ result->remove_at(result, e2);
+ ts2->destroy(ts2);
+ e1->destroy(e1);
+ e1 = result->create_enumerator(result);
+ break;
+ }
+ if (ts1->is_contained_in(ts1, ts2))
+ {
+ result->remove_at(result, e1);
+ ts1->destroy(ts1);
+ e2->destroy(e2);
+ e2 = result->create_enumerator(result);
+ break;
+ }
+ }
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ return result;
+}
+
+/**
+ * Implementation of child_cfg_t.get_updown.
+ */
+static char* get_updown(private_child_cfg_t *this)
+{
+ return this->updown;
+}
+
+/**
+ * Implementation of child_cfg_t.get_hostaccess.
+ */
+static bool get_hostaccess(private_child_cfg_t *this)
+{
+ return this->hostaccess;
+}
+
+/**
+ * Applies jitter to the rekey value. Returns the new rekey value.
+ * Note: The distribution of random values is not perfect, but it
+ * should get the job done.
+ */
+static u_int64_t apply_jitter(u_int64_t rekey, u_int64_t jitter)
+{
+ if (jitter == 0)
+ {
+ return rekey;
+ }
+ jitter = (jitter == UINT64_MAX) ? jitter : jitter + 1;
+ return rekey - jitter * (random() / (RAND_MAX + 1.0));
+}
+#define APPLY_JITTER(l) l.rekey = apply_jitter(l.rekey, l.jitter)
+
+/**
+ * Implementation of child_cfg_t.get_lifetime.
+ */
+static lifetime_cfg_t *get_lifetime(private_child_cfg_t *this)
+{
+ lifetime_cfg_t *lft = malloc_thing(lifetime_cfg_t);
+ memcpy(lft, &this->lifetime, sizeof(lifetime_cfg_t));
+ APPLY_JITTER(lft->time);
+ APPLY_JITTER(lft->bytes);
+ APPLY_JITTER(lft->packets);
+ return lft;
+}
+
+/**
+ * Implementation of child_cfg_t.get_mode.
+ */
+static ipsec_mode_t get_mode(private_child_cfg_t *this)
+{
+ return this->mode;
+}
+
+/**
+ * Implementation of child_cfg_t.get_dpd_action.
+ */
+static action_t get_dpd_action(private_child_cfg_t *this)
+{
+ return this->dpd_action;
+}
+
+/**
+ * Implementation of child_cfg_t.get_close_action.
+ */
+static action_t get_close_action(private_child_cfg_t *this)
+{
+ return this->close_action;
+}
+
+/**
+ * Implementation of child_cfg_t.get_dh_group.
+ */
+static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ proposal_t *proposal;
+ u_int16_t dh_group = MODP_NONE;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return dh_group;
+}
+
+/**
+ * Implementation of child_cfg_t.use_ipcomp.
+ */
+static bool use_ipcomp(private_child_cfg_t *this)
+{
+ return this->use_ipcomp;
+}
+
+/**
+ * Implementation of child_cfg_t.get_inactivity.
+ */
+static u_int32_t get_inactivity(private_child_cfg_t *this)
+{
+ return this->inactivity;
+}
+
+/**
+ * Implementation of child_cfg_t.set_mipv6_options.
+ */
+static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
+ bool install_policy)
+{
+ this->proxy_mode = proxy_mode;
+ this->install_policy = install_policy;
+}
+
+/**
+ * Implementation of child_cfg_t.use_proxy_mode.
+ */
+static bool use_proxy_mode(private_child_cfg_t *this)
+{
+ return this->proxy_mode;
+}
+
+/**
+ * Implementation of child_cfg_t.install_policy.
+ */
+static bool install_policy(private_child_cfg_t *this)
+{
+ return this->install_policy;
+}
+
+/**
+ * Implementation of child_cfg_t.get_ref.
+ */
+static child_cfg_t* get_ref(private_child_cfg_t *this)
+{
+ ref_get(&this->refcount);
+ return &this->public;
+}
+
+/**
+ * Implements child_cfg_t.destroy.
+ */
+static void destroy(private_child_cfg_t *this)
+{
+ if (ref_put(&this->refcount))
+ {
+ this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
+ this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
+ this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
+ if (this->updown)
+ {
+ free(this->updown);
+ }
+ free(this->name);
+ free(this);
+ }
+}
+
+/*
+ * Described in header-file
+ */
+child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
+ char *updown, bool hostaccess,
+ ipsec_mode_t mode, action_t dpd_action,
+ action_t close_action, bool ipcomp,
+ u_int32_t inactivity)
+{
+ private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
+
+ this->public.get_name = (char* (*) (child_cfg_t*))get_name;
+ this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
+ this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
+ this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
+ this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*,bool))get_proposals;
+ this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*,bool,bool))select_proposal;
+ this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
+ this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
+ this->public.get_mode = (ipsec_mode_t (*) (child_cfg_t *))get_mode;
+ this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action;
+ this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action;
+ this->public.get_lifetime = (lifetime_cfg_t* (*) (child_cfg_t *))get_lifetime;
+ this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
+ this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options;
+ this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
+ this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity;
+ this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
+ this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
+ this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
+ this->public.destroy = (void (*) (child_cfg_t*))destroy;
+
+ this->name = strdup(name);
+ this->updown = updown ? strdup(updown) : NULL;
+ this->hostaccess = hostaccess;
+ this->mode = mode;
+ this->dpd_action = dpd_action;
+ this->close_action = close_action;
+ this->use_ipcomp = ipcomp;
+ this->inactivity = inactivity;
+ this->proxy_mode = FALSE;
+ this->install_policy = TRUE;
+ this->refcount = 1;
+ this->proposals = linked_list_create();
+ this->my_ts = linked_list_create();
+ this->other_ts = linked_list_create();
+ memcpy(&this->lifetime, lifetime, sizeof(lifetime_cfg_t));
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
new file mode 100644
index 000000000..c6186ea36
--- /dev/null
+++ b/src/libcharon/config/child_cfg.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup child_cfg child_cfg
+ * @{ @ingroup config
+ */
+
+#ifndef CHILD_CFG_H_
+#define CHILD_CFG_H_
+
+typedef enum action_t action_t;
+typedef enum ipcomp_transform_t ipcomp_transform_t;
+typedef struct lifetime_cfg_t lifetime_cfg_t;
+typedef struct child_cfg_t child_cfg_t;
+
+#include <library.h>
+#include <selectors/traffic_selector.h>
+#include <config/proposal.h>
+#include <kernel/kernel_ipsec.h>
+
+/**
+ * Action to take when DPD detected/connection gets closed by peer.
+ */
+enum action_t {
+ /** No action */
+ ACTION_NONE,
+ /** Route config to reestablish on demand */
+ ACTION_ROUTE,
+ /** Restart config immediately */
+ ACTION_RESTART,
+};
+
+/**
+ * enum names for action_t.
+ */
+extern enum_name_t *action_names;
+
+/**
+ * IPComp transform IDs, as in RFC 4306
+ */
+enum ipcomp_transform_t {
+ IPCOMP_NONE = 241,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4,
+};
+
+/**
+ * enum strings for ipcomp_transform_t.
+ */
+extern enum_name_t *ipcomp_transform_names;
+
+/**
+ * A lifetime_cfg_t defines the lifetime limits of a CHILD_SA.
+ *
+ * Set any of these values to 0 to ignore.
+ */
+struct lifetime_cfg_t {
+ struct {
+ /** Limit before the CHILD_SA gets invalid. */
+ u_int64_t life;
+ /** Limit before the CHILD_SA gets rekeyed. */
+ u_int64_t rekey;
+ /** The range of a random value subtracted from rekey. */
+ u_int64_t jitter;
+ } time, bytes, packets;
+};
+
+/**
+ * A child_cfg_t defines the config template for a CHILD_SA.
+ *
+ * After creation, proposals and traffic selectors may be added to the config.
+ * A child_cfg object is referenced multiple times, and is not thread save.
+ * Reading from the object is save, adding things is not allowed while other
+ * threads may access the object.
+ * A reference counter handles the number of references hold to this config.
+ *
+ * @see peer_cfg_t to get an overview over the configurations.
+ */
+struct child_cfg_t {
+
+ /**
+ * Get the name of the child_cfg.
+ *
+ * @return child_cfg's name
+ */
+ char *(*get_name) (child_cfg_t *this);
+
+ /**
+ * Add a proposal to the list.
+ *
+ * The proposals are stored by priority, first added
+ * is the most prefered.
+ * After add, proposal is owned by child_cfg.
+ *
+ * @param proposal proposal to add
+ */
+ void (*add_proposal) (child_cfg_t *this, proposal_t *proposal);
+
+ /**
+ * Get the list of proposals for the CHILD_SA.
+ *
+ * Resulting list and all of its proposals must be freed after use.
+ *
+ * @param strip_dh TRUE strip out diffie hellman groups
+ * @return list of proposals
+ */
+ linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_dh);
+
+ /**
+ * Select a proposal from a supplied list.
+ *
+ * Returned propsal is newly created and must be destroyed after usage.
+ *
+ * @param proposals list from from wich proposals are selected
+ * @param strip_dh TRUE strip out diffie hellman groups
+ * @param private accept algorithms from a private range
+ * @return selected proposal, or NULL if nothing matches
+ */
+ proposal_t* (*select_proposal)(child_cfg_t*this, linked_list_t *proposals,
+ bool strip_dh, bool private);
+
+ /**
+ * Add a traffic selector to the config.
+ *
+ * Use the "local" parameter to add it for the local or the remote side.
+ * After add, traffic selector is owned by child_cfg.
+ *
+ * @param local TRUE for local side, FALSE for remote
+ * @param ts traffic_selector to add
+ */
+ void (*add_traffic_selector)(child_cfg_t *this, bool local,
+ traffic_selector_t *ts);
+
+ /**
+ * Get a list of traffic selectors to use for the CHILD_SA.
+ *
+ * The config contains two set of traffic selectors, one for the local
+ * side, one for the remote side.
+ * If a list with traffic selectors is supplied, these are used to narrow
+ * down the traffic selector list to the greatest common divisor.
+ * Some traffic selector may be "dymamic", meaning they are narrowed down
+ * to a specific address (host-to-host or virtual-IP setups). Use
+ * the "host" parameter to narrow such traffic selectors to that address.
+ * Resulted list and its traffic selectors must be destroyed after use.
+ *
+ * @param local TRUE for TS on local side, FALSE for remote
+ * @param supplied list with TS to select from, or NULL
+ * @param host address to use for narrowing "dynamic" TS', or NULL
+ * @return list containing the traffic selectors
+ */
+ linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
+ linked_list_t *supplied,
+ host_t *host);
+ /**
+ * Get the updown script to run for the CHILD_SA.
+ *
+ * @return path to updown script
+ */
+ char* (*get_updown)(child_cfg_t *this);
+
+ /**
+ * Should we allow access to the local host (gateway)?
+ *
+ * @return value of hostaccess flag
+ */
+ bool (*get_hostaccess) (child_cfg_t *this);
+
+ /**
+ * Get the lifetime configuration of a CHILD_SA.
+ *
+ * The rekey limits automatically contain a jitter to avoid simultaneous
+ * rekeying. These values will change with each call to this function.
+ *
+ * @return lifetime_cfg_t (has to be freed)
+ */
+ lifetime_cfg_t* (*get_lifetime) (child_cfg_t *this);
+
+ /**
+ * Get the mode to use for the CHILD_SA.
+ *
+ * The mode is either tunnel, transport or BEET. The peer must agree
+ * on the method, fallback is tunnel mode.
+ *
+ * @return ipsec mode
+ */
+ ipsec_mode_t (*get_mode) (child_cfg_t *this);
+
+ /**
+ * Action to take on DPD.
+ *
+ * @return DPD action
+ */
+ action_t (*get_dpd_action) (child_cfg_t *this);
+
+ /**
+ * Action to take if CHILD_SA gets closed.
+ *
+ * @return close action
+ */
+ action_t (*get_close_action) (child_cfg_t *this);
+
+ /**
+ * Get the DH group to use for CHILD_SA setup.
+ *
+ * @return dh group to use
+ */
+ diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this);
+
+ /**
+ * Check whether IPComp should be used, if the other peer supports it.
+ *
+ * @return TRUE, if IPComp should be used
+ * FALSE, otherwise
+ */
+ bool (*use_ipcomp)(child_cfg_t *this);
+
+ /**
+ * Get the inactivity timeout value.
+ *
+ * @return inactivity timeout in s
+ */
+ u_int32_t (*get_inactivity)(child_cfg_t *this);
+
+ /**
+ * Sets two options needed for Mobile IPv6 interoperability
+ *
+ * @param proxy_mode use IPsec transport proxy mode (default FALSE)
+ * @param install_policy install IPsec kernel policies (default TRUE)
+ */
+ void (*set_mipv6_options)(child_cfg_t *this, bool proxy_mode,
+ bool install_policy);
+
+ /**
+ * Check whether IPsec transport SA should be set up in proxy mode
+ *
+ * @return TRUE, if proxy mode should be used
+ * FALSE, otherwise
+ */
+ bool (*use_proxy_mode)(child_cfg_t *this);
+
+ /**
+ * Check whether IPsec policies should be installed in the kernel
+ *
+ * @return TRUE, if IPsec kernel policies should be installed
+ * FALSE, otherwise
+ */
+ bool (*install_policy)(child_cfg_t *this);
+
+ /**
+ * Increase the reference count.
+ *
+ * @return reference to this
+ */
+ child_cfg_t* (*get_ref) (child_cfg_t *this);
+
+ /**
+ * Destroys the child_cfg object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the child_cfg when it reaches zero.
+ */
+ void (*destroy) (child_cfg_t *this);
+};
+
+/**
+ * Create a configuration template for CHILD_SA setup.
+ *
+ * The "name" string gets cloned.
+ *
+ * The lifetime_cfg_t object gets cloned.
+ * To prevent two peers to start rekeying at the same time, a jitter may be
+ * specified. Rekeying of an SA starts at (x.rekey - random(0, x.jitter)).
+ *
+ * After a call to create, a reference is obtained (refcount = 1).
+ *
+ * @param name name of the child_cfg
+ * @param lifetime lifetime_cfg_t for this child_cfg
+ * @param updown updown script to execute on up/down event
+ * @param hostaccess TRUE to allow access to the local host
+ * @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
+ * @param dpd_action DPD action
+ * @param close_action close action
+ * @param ipcomp use IPComp, if peer supports it
+ * @param inactivity inactivity timeout in s before closing a CHILD_SA
+ * @return child_cfg_t object
+ */
+child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
+ char *updown, bool hostaccess,
+ ipsec_mode_t mode, action_t dpd_action,
+ action_t close_action, bool ipcomp,
+ u_int32_t inactivity);
+
+#endif /** CHILD_CFG_H_ @}*/
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
new file mode 100644
index 000000000..89dcd8022
--- /dev/null
+++ b/src/libcharon/config/ike_cfg.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_cfg.h"
+
+#include <string.h>
+
+#include <daemon.h>
+
+
+typedef struct private_ike_cfg_t private_ike_cfg_t;
+
+/**
+ * Private data of an ike_cfg_t object
+ */
+struct private_ike_cfg_t {
+
+ /**
+ * Public part
+ */
+ ike_cfg_t public;
+
+ /**
+ * Number of references hold by others to this ike_cfg
+ */
+ refcount_t refcount;
+
+ /**
+ * Address of local host
+ */
+ char *me;
+
+ /**
+ * Address of remote host
+ */
+ char *other;
+
+ /**
+ * our source port
+ */
+ u_int16_t my_port;
+
+ /**
+ * destination port
+ */
+ u_int16_t other_port;
+
+ /**
+ * should we send a certificate request?
+ */
+ bool certreq;
+
+ /**
+ * enforce UDP encapsulation
+ */
+ bool force_encap;
+
+ /**
+ * List of proposals to use
+ */
+ linked_list_t *proposals;
+};
+
+METHOD(ike_cfg_t, send_certreq, bool,
+ private_ike_cfg_t *this)
+{
+ return this->certreq;
+}
+
+METHOD(ike_cfg_t, force_encap_, bool,
+ private_ike_cfg_t *this)
+{
+ return this->force_encap;
+}
+
+METHOD(ike_cfg_t, get_my_addr, char*,
+ private_ike_cfg_t *this)
+{
+ return this->me;
+}
+
+METHOD(ike_cfg_t, get_other_addr, char*,
+ private_ike_cfg_t *this)
+{
+ return this->other;
+}
+
+METHOD(ike_cfg_t, get_my_port, u_int16_t,
+ private_ike_cfg_t *this)
+{
+ return this->my_port;
+}
+
+METHOD(ike_cfg_t, get_other_port, u_int16_t,
+ private_ike_cfg_t *this)
+{
+ return this->other_port;
+}
+
+METHOD(ike_cfg_t, add_proposal, void,
+ private_ike_cfg_t *this, proposal_t *proposal)
+{
+ this->proposals->insert_last(this->proposals, proposal);
+}
+
+METHOD(ike_cfg_t, get_proposals, linked_list_t*,
+ private_ike_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ proposal_t *current;
+ linked_list_t *proposals;
+
+ proposals = linked_list_create();
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current = current->clone(current);
+ proposals->insert_last(proposals, current);
+ }
+ enumerator->destroy(enumerator);
+
+ return proposals;
+}
+
+METHOD(ike_cfg_t, select_proposal, proposal_t*,
+ private_ike_cfg_t *this, linked_list_t *proposals, bool private)
+{
+ iterator_t *stored_iter, *supplied_iter;
+ proposal_t *stored, *supplied, *selected;
+
+ stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
+ supplied_iter = proposals->create_iterator(proposals, TRUE);
+
+
+ /* compare all stored proposals with all supplied. Stored ones are preferred.*/
+ while (stored_iter->iterate(stored_iter, (void**)&stored))
+ {
+ supplied_iter->reset(supplied_iter);
+
+ while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
+ {
+ selected = stored->select(stored, supplied, private);
+ if (selected)
+ {
+ /* they match, return */
+ stored_iter->destroy(stored_iter);
+ supplied_iter->destroy(supplied_iter);
+ DBG2(DBG_CFG, "received proposals: %#P", proposals);
+ DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
+ DBG2(DBG_CFG, "selected proposal: %P", selected);
+ return selected;
+ }
+ }
+ }
+ /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
+ stored_iter->destroy(stored_iter);
+ supplied_iter->destroy(supplied_iter);
+ DBG1(DBG_CFG, "received proposals: %#P", proposals);
+ DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
+
+ return NULL;
+}
+
+METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
+ private_ike_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ proposal_t *proposal;
+ u_int16_t dh_group = MODP_NONE;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return dh_group;
+}
+
+METHOD(ike_cfg_t, equals, bool,
+ private_ike_cfg_t *this, ike_cfg_t *other_public)
+{
+ private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
+ enumerator_t *e1, *e2;
+ proposal_t *p1, *p2;
+ bool eq = TRUE;
+
+ if (this == other)
+ {
+ return TRUE;
+ }
+ if (this->public.equals != other->public.equals)
+ {
+ return FALSE;
+ }
+ if (this->proposals->get_count(this->proposals) !=
+ other->proposals->get_count(other->proposals))
+ {
+ return FALSE;
+ }
+ e1 = this->proposals->create_enumerator(this->proposals);
+ e2 = this->proposals->create_enumerator(this->proposals);
+ while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
+ {
+ if (!p1->equals(p1, p2))
+ {
+ eq = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ return (eq &&
+ this->certreq == other->certreq &&
+ this->force_encap == other->force_encap &&
+ streq(this->me, other->me) &&
+ streq(this->other, other->other) &&
+ this->my_port == other->my_port &&
+ this->other_port == other->other_port);
+}
+
+METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
+ private_ike_cfg_t *this)
+{
+ ref_get(&this->refcount);
+ return &this->public;
+}
+
+METHOD(ike_cfg_t, destroy, void,
+ private_ike_cfg_t *this)
+{
+ if (ref_put(&this->refcount))
+ {
+ this->proposals->destroy_offset(this->proposals,
+ offsetof(proposal_t, destroy));
+ free(this->me);
+ free(this->other);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
+ char *me, u_int16_t my_port, char *other, u_int16_t other_port)
+{
+ private_ike_cfg_t *this;
+
+ INIT(this,
+ .public = {
+ .send_certreq = _send_certreq,
+ .force_encap = _force_encap_,
+ .get_my_addr = _get_my_addr,
+ .get_other_addr = _get_other_addr,
+ .get_my_port = _get_my_port,
+ .get_other_port = _get_other_port,
+ .add_proposal = _add_proposal,
+ .get_proposals = _get_proposals,
+ .select_proposal = _select_proposal,
+ .get_dh_group = _get_dh_group,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .refcount = 1,
+ .certreq = certreq,
+ .force_encap = force_encap,
+ .me = strdup(me),
+ .other = strdup(other),
+ .my_port = my_port,
+ .other_port = other_port,
+ .proposals = linked_list_create(),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
new file mode 100644
index 000000000..f1edde255
--- /dev/null
+++ b/src/libcharon/config/ike_cfg.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_cfg ike_cfg
+ * @{ @ingroup config
+ */
+
+#ifndef IKE_CFG_H_
+#define IKE_CFG_H_
+
+typedef struct ike_cfg_t ike_cfg_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <config/proposal.h>
+#include <crypto/diffie_hellman.h>
+
+/**
+ * An ike_cfg_t defines the rules to set up an IKE_SA.
+ *
+ * @see peer_cfg_t to get an overview over the configurations.
+ */
+struct ike_cfg_t {
+
+ /**
+ * Get own address.
+ *
+ * @return string of address/DNS name
+ */
+ char* (*get_my_addr) (ike_cfg_t *this);
+
+ /**
+ * Get peers address.
+ *
+ * @return string of address/DNS name
+ */
+ char* (*get_other_addr) (ike_cfg_t *this);
+
+ /**
+ * Get the port to use as our source port.
+ *
+ * @return source address port, host order
+ */
+ u_int16_t (*get_my_port)(ike_cfg_t *this);
+
+ /**
+ * Get the port to use as destination port.
+ *
+ * @return destination address, host order
+ */
+ u_int16_t (*get_other_port)(ike_cfg_t *this);
+
+ /**
+ * Adds a proposal to the list.
+ *
+ * The first added proposal has the highest priority, the last
+ * added the lowest.
+ *
+ * @param proposal proposal to add
+ */
+ void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal);
+
+ /**
+ * Returns a list of all supported proposals.
+ *
+ * Returned list and its proposals must be destroyed after use.
+ *
+ * @return list containing all the proposals
+ */
+ linked_list_t* (*get_proposals) (ike_cfg_t *this);
+
+ /**
+ * Select a proposed from suggested proposals.
+ *
+ * Returned proposal must be destroyed after use.
+ *
+ * @param proposals list of proposals to select from
+ * @param private accept algorithms from a private range
+ * @return selected proposal, or NULL if none matches.
+ */
+ proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals,
+ bool private);
+
+ /**
+ * Should we send a certificate request in IKE_SA_INIT?
+ *
+ * @return certificate request sending policy
+ */
+ bool (*send_certreq) (ike_cfg_t *this);
+
+ /**
+ * Enforce UDP encapsulation by faking NATD notifies?
+ *
+ * @return TRUE to enfoce UDP encapsulation
+ */
+ bool (*force_encap) (ike_cfg_t *this);
+
+ /**
+ * Get the DH group to use for IKE_SA setup.
+ *
+ * @return dh group to use for initialization
+ */
+ diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this);
+
+ /**
+ * Check if two IKE configs are equal.
+ *
+ * @param other other to check for equality
+ * @return TRUE if other equal to this
+ */
+ bool (*equals)(ike_cfg_t *this, ike_cfg_t *other);
+
+ /**
+ * Increase reference count.
+ *
+ * @return reference to this
+ */
+ ike_cfg_t* (*get_ref) (ike_cfg_t *this);
+
+ /**
+ * Destroys a ike_cfg_t object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the ike_cfg when it reaches zero.
+ */
+ void (*destroy) (ike_cfg_t *this);
+};
+
+/**
+ * Creates a ike_cfg_t object.
+ *
+ * Supplied hosts become owned by ike_cfg, the name gets cloned.
+ *
+ * @param certreq TRUE to send a certificate request
+ * @param force_encap enforce UDP encapsulation by faking NATD notify
+ * @param me address/DNS name of local peer
+ * @param my_port IKE port to use as source, 500 uses IKEv2 port floating
+ * @param other address/DNS name of remote peer
+ * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating
+ * @return ike_cfg_t object.
+ */
+ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
+ char *me, u_int16_t my_port, char *other, u_int16_t other_port);
+
+#endif /** IKE_CFG_H_ @}*/
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
new file mode 100644
index 000000000..9df14c9ae
--- /dev/null
+++ b/src/libcharon/config/peer_cfg.c
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+
+#include "peer_cfg.h"
+
+#include <daemon.h>
+
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+
+ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
+ "CERT_ALWAYS_SEND",
+ "CERT_SEND_IF_ASKED",
+ "CERT_NEVER_SEND",
+);
+
+ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
+ "UNIQUE_NO",
+ "UNIQUE_REPLACE",
+ "UNIQUE_KEEP",
+);
+
+typedef struct private_peer_cfg_t private_peer_cfg_t;
+
+/**
+ * Private data of an peer_cfg_t object
+ */
+struct private_peer_cfg_t {
+
+ /**
+ * Public part
+ */
+ peer_cfg_t public;
+
+ /**
+ * Number of references hold by others to this peer_cfg
+ */
+ refcount_t refcount;
+
+ /**
+ * Name of the peer_cfg, used to query it
+ */
+ char *name;
+
+ /**
+ * IKE version to use for initiation
+ */
+ u_int ike_version;
+
+ /**
+ * IKE config associated to this peer config
+ */
+ ike_cfg_t *ike_cfg;
+
+ /**
+ * list of child configs associated to this peer config
+ */
+ linked_list_t *child_cfgs;
+
+ /**
+ * mutex to lock access to list of child_cfgs
+ */
+ mutex_t *mutex;
+
+ /**
+ * should we send a certificate
+ */
+ cert_policy_t cert_policy;
+
+ /**
+ * uniqueness of an IKE_SA
+ */
+ unique_policy_t unique;
+
+ /**
+ * number of tries after giving up if peer does not respond
+ */
+ u_int32_t keyingtries;
+
+ /**
+ * enable support for MOBIKE
+ */
+ bool use_mobike;
+
+ /**
+ * Time before starting rekeying
+ */
+ u_int32_t rekey_time;
+
+ /**
+ * Time before starting reauthentication
+ */
+ u_int32_t reauth_time;
+
+ /**
+ * Time, which specifies the range of a random value substracted from above.
+ */
+ u_int32_t jitter_time;
+
+ /**
+ * Delay before deleting a rekeying/reauthenticating SA
+ */
+ u_int32_t over_time;
+
+ /**
+ * DPD check intervall
+ */
+ u_int32_t dpd;
+
+ /**
+ * virtual IP to use locally
+ */
+ host_t *virtual_ip;
+
+ /**
+ * pool to acquire configuration attributes from
+ */
+ char *pool;
+
+ /**
+ * local authentication configs (rulesets)
+ */
+ linked_list_t *local_auth;
+
+ /**
+ * remote authentication configs (constraints)
+ */
+ linked_list_t *remote_auth;
+
+#ifdef ME
+ /**
+ * Is this a mediation connection?
+ */
+ bool mediation;
+
+ /**
+ * Name of the mediation connection to mediate through
+ */
+ peer_cfg_t *mediated_by;
+
+ /**
+ * ID of our peer at the mediation server (= leftid of the peer's conn with
+ * the mediation server)
+ */
+ identification_t *peer_id;
+#endif /* ME */
+};
+
+/**
+ * Implementation of peer_cfg_t.get_name
+ */
+static char *get_name(private_peer_cfg_t *this)
+{
+ return this->name;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_ike_version
+ */
+static u_int get_ike_version(private_peer_cfg_t *this)
+{
+ return this->ike_version;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_ike_cfg
+ */
+static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
+{
+ return this->ike_cfg;
+}
+
+/**
+ * Implementation of peer_cfg_t.add_child_cfg.
+ */
+static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
+{
+ this->mutex->lock(this->mutex);
+ this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * child_cfg enumerator
+ */
+typedef struct {
+ enumerator_t public;
+ enumerator_t *wrapped;
+ mutex_t *mutex;
+} child_cfg_enumerator_t;
+
+/**
+ * Implementation of peer_cfg_t.remove_child_cfg.
+ */
+static void remove_child_cfg(private_peer_cfg_t *this,
+ child_cfg_enumerator_t *enumerator)
+{
+ this->child_cfgs->remove_at(this->child_cfgs, enumerator->wrapped);
+}
+
+/**
+ * Implementation of child_cfg_enumerator_t.destroy
+ */
+static void child_cfg_enumerator_destroy(child_cfg_enumerator_t *this)
+{
+ this->mutex->unlock(this->mutex);
+ this->wrapped->destroy(this->wrapped);
+ free(this);
+}
+
+/**
+ * Implementation of child_cfg_enumerator_t.enumerate
+ */
+static bool child_cfg_enumerate(child_cfg_enumerator_t *this, child_cfg_t **chd)
+{
+ return this->wrapped->enumerate(this->wrapped, chd);
+}
+
+/**
+ * Implementation of peer_cfg_t.create_child_cfg_enumerator.
+ */
+static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this)
+{
+ child_cfg_enumerator_t *enumerator = malloc_thing(child_cfg_enumerator_t);
+
+ enumerator->public.enumerate = (void*)child_cfg_enumerate;
+ enumerator->public.destroy = (void*)child_cfg_enumerator_destroy;
+ enumerator->mutex = this->mutex;
+ enumerator->wrapped = this->child_cfgs->create_enumerator(this->child_cfgs);
+
+ this->mutex->lock(this->mutex);
+ return &enumerator->public;
+}
+
+/**
+ * Check how good a list of TS matches a given child config
+ */
+static int get_ts_match(child_cfg_t *cfg, bool local,
+ linked_list_t *sup_list, host_t *host)
+{
+ linked_list_t *cfg_list;
+ enumerator_t *sup_enum, *cfg_enum;
+ traffic_selector_t *sup_ts, *cfg_ts;
+ int match = 0, round;
+
+ /* fetch configured TS list, narrowing dynamic TS */
+ cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, host);
+
+ /* use a round counter to rate leading TS with higher priority */
+ round = sup_list->get_count(sup_list);
+
+ sup_enum = sup_list->create_enumerator(sup_list);
+ while (sup_enum->enumerate(sup_enum, &sup_ts))
+ {
+ cfg_enum = cfg_list->create_enumerator(cfg_list);
+ while (cfg_enum->enumerate(cfg_enum, &cfg_ts))
+ {
+ if (cfg_ts->equals(cfg_ts, sup_ts))
+ { /* equality is honored better than matches */
+ match += round * 5;
+ }
+ else if (cfg_ts->is_contained_in(cfg_ts, sup_ts) ||
+ sup_ts->is_contained_in(sup_ts, cfg_ts))
+ {
+ match += round * 1;
+ }
+ }
+ cfg_enum->destroy(cfg_enum);
+ round--;
+ }
+ sup_enum->destroy(sup_enum);
+
+ cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
+
+ return match;
+}
+
+/**
+ * Implementation of peer_cfg_t.select_child_cfg
+ */
+static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
+ linked_list_t *my_ts,
+ linked_list_t *other_ts,
+ host_t *my_host, host_t *other_host)
+{
+ child_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+ int best = 0;
+
+ DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
+ enumerator = create_child_cfg_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ int my_prio, other_prio;
+
+ my_prio = get_ts_match(current, TRUE, my_ts, my_host);
+ other_prio = get_ts_match(current, FALSE, other_ts, other_host);
+
+ if (my_prio && other_prio)
+ {
+ DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
+ current->get_name(current), my_prio, other_prio);
+ if (my_prio + other_prio > best)
+ {
+ best = my_prio + other_prio;
+ DESTROY_IF(found);
+ found = current->get_ref(current);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
+ found->get_name(found), best);
+ }
+ return found;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_cert_policy.
+ */
+static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
+{
+ return this->cert_policy;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_unique_policy.
+ */
+static unique_policy_t get_unique_policy(private_peer_cfg_t *this)
+{
+ return this->unique;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_keyingtries.
+ */
+static u_int32_t get_keyingtries(private_peer_cfg_t *this)
+{
+ return this->keyingtries;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_rekey_time.
+ */
+static u_int32_t get_rekey_time(private_peer_cfg_t *this)
+{
+ if (this->rekey_time == 0)
+ {
+ return 0;
+ }
+ if (this->jitter_time == 0)
+ {
+ return this->rekey_time;
+ }
+ return this->rekey_time - (random() % this->jitter_time);
+}
+
+/**
+ * Implementation of peer_cfg_t.get_reauth_time.
+ */
+static u_int32_t get_reauth_time(private_peer_cfg_t *this)
+{
+ if (this->reauth_time == 0)
+ {
+ return 0;
+ }
+ if (this->jitter_time == 0)
+ {
+ return this->reauth_time;
+ }
+ return this->reauth_time - (random() % this->jitter_time);
+}
+
+/**
+ * Implementation of peer_cfg_t.get_over_time.
+ */
+static u_int32_t get_over_time(private_peer_cfg_t *this)
+{
+ return this->over_time;
+}
+
+/**
+ * Implementation of peer_cfg_t.use_mobike.
+ */
+static bool use_mobike(private_peer_cfg_t *this)
+{
+ return this->use_mobike;
+}
+
+/**
+ * Implements peer_cfg_t.get_dpd
+ */
+static u_int32_t get_dpd(private_peer_cfg_t *this)
+{
+ return this->dpd;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_virtual_ip.
+ */
+static host_t* get_virtual_ip(private_peer_cfg_t *this)
+{
+ return this->virtual_ip;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_pool.
+ */
+static char* get_pool(private_peer_cfg_t *this)
+{
+ return this->pool;
+}
+
+/**
+ * Implementation of peer_cfg_t.add_auth_cfg
+ */
+static void add_auth_cfg(private_peer_cfg_t *this,
+ auth_cfg_t *cfg, bool local)
+{
+ if (local)
+ {
+ this->local_auth->insert_last(this->local_auth, cfg);
+ }
+ else
+ {
+ this->remote_auth->insert_last(this->remote_auth, cfg);
+ }
+}
+
+/**
+ * Implementation of peer_cfg_t.create_auth_cfg_enumerator
+ */
+static enumerator_t* create_auth_cfg_enumerator(private_peer_cfg_t *this,
+ bool local)
+{
+ if (local)
+ {
+ return this->local_auth->create_enumerator(this->local_auth);
+ }
+ return this->remote_auth->create_enumerator(this->remote_auth);
+}
+
+#ifdef ME
+/**
+ * Implementation of peer_cfg_t.is_mediation.
+ */
+static bool is_mediation(private_peer_cfg_t *this)
+{
+ return this->mediation;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_mediated_by.
+ */
+static peer_cfg_t* get_mediated_by(private_peer_cfg_t *this)
+{
+ return this->mediated_by;
+}
+
+/**
+ * Implementation of peer_cfg_t.get_peer_id.
+ */
+static identification_t* get_peer_id(private_peer_cfg_t *this)
+{
+ return this->peer_id;
+}
+#endif /* ME */
+
+/**
+ * check auth configs for equality
+ */
+static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
+{
+ enumerator_t *e1, *e2;
+ auth_cfg_t *cfg1, *cfg2;
+ bool equal = TRUE;
+
+ if (this->local_auth->get_count(this->local_auth) !=
+ other->local_auth->get_count(other->local_auth))
+ {
+ return FALSE;
+ }
+ if (this->remote_auth->get_count(this->remote_auth) !=
+ other->remote_auth->get_count(other->remote_auth))
+ {
+ return FALSE;
+ }
+
+ e1 = this->local_auth->create_enumerator(this->local_auth);
+ e2 = other->local_auth->create_enumerator(other->local_auth);
+ while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
+ {
+ if (!cfg1->equals(cfg1, cfg2))
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ if (!equal)
+ {
+ return FALSE;
+ }
+
+ e1 = this->remote_auth->create_enumerator(this->remote_auth);
+ e2 = other->remote_auth->create_enumerator(other->remote_auth);
+ while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
+ {
+ if (!cfg1->equals(cfg1, cfg2))
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ return equal;
+}
+
+/**
+ * Implementation of peer_cfg_t.equals.
+ */
+static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
+{
+ if (this == other)
+ {
+ return TRUE;
+ }
+ if (this->public.equals != other->public.equals)
+ {
+ return FALSE;
+ }
+
+ return (
+ this->ike_version == other->ike_version &&
+ this->cert_policy == other->cert_policy &&
+ this->unique == other->unique &&
+ this->keyingtries == other->keyingtries &&
+ this->use_mobike == other->use_mobike &&
+ this->rekey_time == other->rekey_time &&
+ this->reauth_time == other->reauth_time &&
+ this->jitter_time == other->jitter_time &&
+ this->over_time == other->over_time &&
+ this->dpd == other->dpd &&
+ (this->virtual_ip == other->virtual_ip ||
+ (this->virtual_ip && other->virtual_ip &&
+ this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
+ (this->pool == other->pool ||
+ (this->pool && other->pool && streq(this->pool, other->pool))) &&
+ auth_cfg_equal(this, other)
+#ifdef ME
+ && this->mediation == other->mediation &&
+ this->mediated_by == other->mediated_by &&
+ (this->peer_id == other->peer_id ||
+ (this->peer_id && other->peer_id &&
+ this->peer_id->equals(this->peer_id, other->peer_id)))
+#endif /* ME */
+ );
+}
+
+/**
+ * Implements peer_cfg_t.get_ref.
+ */
+static peer_cfg_t* get_ref(private_peer_cfg_t *this)
+{
+ ref_get(&this->refcount);
+ return &this->public;
+}
+
+/**
+ * Implements peer_cfg_t.destroy.
+ */
+static void destroy(private_peer_cfg_t *this)
+{
+ if (ref_put(&this->refcount))
+ {
+ this->ike_cfg->destroy(this->ike_cfg);
+ this->child_cfgs->destroy_offset(this->child_cfgs,
+ offsetof(child_cfg_t, destroy));
+ DESTROY_IF(this->virtual_ip);
+ this->local_auth->destroy_offset(this->local_auth,
+ offsetof(auth_cfg_t, destroy));
+ this->remote_auth->destroy_offset(this->remote_auth,
+ offsetof(auth_cfg_t, destroy));
+#ifdef ME
+ DESTROY_IF(this->mediated_by);
+ DESTROY_IF(this->peer_id);
+#endif /* ME */
+ this->mutex->destroy(this->mutex);
+ free(this->name);
+ free(this->pool);
+ free(this);
+ }
+}
+
+/*
+ * Described in header-file
+ */
+peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
+ cert_policy_t cert_policy, unique_policy_t unique,
+ u_int32_t keyingtries, u_int32_t rekey_time,
+ u_int32_t reauth_time, u_int32_t jitter_time,
+ u_int32_t over_time, bool mobike, u_int32_t dpd,
+ host_t *virtual_ip, char *pool,
+ bool mediation, peer_cfg_t *mediated_by,
+ identification_t *peer_id)
+{
+ private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
+
+ /* public functions */
+ this->public.get_name = (char* (*) (peer_cfg_t *))get_name;
+ this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version;
+ this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg;
+ this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg;
+ this->public.remove_child_cfg = (void(*)(peer_cfg_t*, enumerator_t*))remove_child_cfg;
+ this->public.create_child_cfg_enumerator = (enumerator_t* (*) (peer_cfg_t *))create_child_cfg_enumerator;
+ this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg;
+ this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
+ this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy;
+ this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
+ this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time;
+ this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time;
+ this->public.get_over_time = (u_int32_t(*)(peer_cfg_t*))get_over_time;
+ this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike;
+ this->public.get_dpd = (u_int32_t (*) (peer_cfg_t *))get_dpd;
+ this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *))get_virtual_ip;
+ this->public.get_pool = (char*(*)(peer_cfg_t*))get_pool;
+ this->public.add_auth_cfg = (void(*)(peer_cfg_t*, auth_cfg_t *cfg, bool local))add_auth_cfg;
+ this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(peer_cfg_t*, bool local))create_auth_cfg_enumerator;
+ this->public.equals = (bool(*)(peer_cfg_t*, peer_cfg_t *other))equals;
+ this->public.get_ref = (peer_cfg_t*(*)(peer_cfg_t *))get_ref;
+ this->public.destroy = (void(*)(peer_cfg_t *))destroy;
+#ifdef ME
+ this->public.is_mediation = (bool (*) (peer_cfg_t *))is_mediation;
+ this->public.get_mediated_by = (peer_cfg_t* (*) (peer_cfg_t *))get_mediated_by;
+ this->public.get_peer_id = (identification_t* (*) (peer_cfg_t *))get_peer_id;
+#endif /* ME */
+
+ /* apply init values */
+ this->name = strdup(name);
+ this->ike_version = ike_version;
+ this->ike_cfg = ike_cfg;
+ this->child_cfgs = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->cert_policy = cert_policy;
+ this->unique = unique;
+ this->keyingtries = keyingtries;
+ this->rekey_time = rekey_time;
+ this->reauth_time = reauth_time;
+ if (rekey_time && jitter_time > rekey_time)
+ {
+ jitter_time = rekey_time;
+ }
+ if (reauth_time && jitter_time > reauth_time)
+ {
+ jitter_time = reauth_time;
+ }
+ this->jitter_time = jitter_time;
+ this->over_time = over_time;
+ this->use_mobike = mobike;
+ this->dpd = dpd;
+ this->virtual_ip = virtual_ip;
+ this->pool = pool ? strdup(pool) : NULL;
+ this->local_auth = linked_list_create();
+ this->remote_auth = linked_list_create();
+ this->refcount = 1;
+#ifdef ME
+ this->mediation = mediation;
+ this->mediated_by = mediated_by;
+ this->peer_id = peer_id;
+#else /* ME */
+ DESTROY_IF(mediated_by);
+ DESTROY_IF(peer_id);
+#endif /* ME */
+
+ return &this->public;
+}
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
new file mode 100644
index 000000000..6855276f8
--- /dev/null
+++ b/src/libcharon/config/peer_cfg.h
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup peer_cfg peer_cfg
+ * @{ @ingroup config
+ */
+
+#ifndef PEER_CFG_H_
+#define PEER_CFG_H_
+
+typedef enum cert_policy_t cert_policy_t;
+typedef enum unique_policy_t unique_policy_t;
+typedef struct peer_cfg_t peer_cfg_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+#include <selectors/traffic_selector.h>
+#include <config/proposal.h>
+#include <config/ike_cfg.h>
+#include <config/child_cfg.h>
+#include <sa/authenticators/authenticator.h>
+#include <sa/authenticators/eap/eap_method.h>
+#include <config/auth_cfg.h>
+
+/**
+ * Certificate sending policy. This is also used for certificate
+ * requests when using this definition for the other peer. If
+ * it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
+ * included.
+ *
+ * @warning These definitions must be the same as in pluto/starter,
+ * as they are sent over the stroke socket.
+ */
+enum cert_policy_t {
+ /** always send certificates, even when not requested */
+ CERT_ALWAYS_SEND = 0,
+ /** send certificate upon cert request */
+ CERT_SEND_IF_ASKED = 1,
+ /** never send a certificate, even when requested */
+ CERT_NEVER_SEND = 2,
+};
+
+/**
+ * enum strings for cert_policy_t
+ */
+extern enum_name_t *cert_policy_names;
+
+/**
+ * Uniqueness of an IKE_SA, used to drop multiple connections with one peer.
+ */
+enum unique_policy_t {
+ /** do not check for client uniqueness */
+ UNIQUE_NO,
+ /** replace unique IKE_SAs if new ones get established */
+ UNIQUE_REPLACE,
+ /** keep existing IKE_SAs, close the new ones on connection attept */
+ UNIQUE_KEEP,
+};
+
+/**
+ * enum strings for unique_policy_t
+ */
+extern enum_name_t *unique_policy_names;
+
+/**
+ * Configuration of a peer, specified by IDs.
+ *
+ * The peer config defines a connection between two given IDs. It contains
+ * exactly one ike_cfg_t, which is use for initiation. Additionally, it contains
+ * multiple child_cfg_t defining which CHILD_SAs are allowed for this peer.
+ * @verbatim
+ +-------------------+ +---------------+
+ +---------------+ | peer_cfg | +---------------+ |
+ | ike_cfg | +-------------------+ | child_cfg | |
+ +---------------+ | - ids | +---------------+ |
+ | - hosts | 1 1 | - cas | 1 n | - proposals | |
+ | - proposals |<-----| - auth info |----->| - traffic sel | |
+ | - ... | | - dpd config | | - ... |-+
+ +---------------+ | - ... | +---------------+
+ +-------------------+
+ | 1 0 |
+ | |
+ v n n V
+ +-------------------+ +-------------------+
+ +-------------------+ | +-------------------+ |
+ | auth_cfg | | | auth_cfg | |
+ +-------------------+ | +-------------------+ |
+ | - local rules |-+ | - remote constr. |-+
+ +-------------------+ +-------------------+
+ @endverbatim
+ *
+ * Each peer_cfg has two lists of authentication config attached. Local
+ * authentication configs define how to authenticate ourself against the remote
+ * peer. Each config is enforced using the multiple authentication extension
+ * (RFC4739).
+ * The remote authentication configs are handled as constraints. The peer has
+ * to fullfill each of these rules (using multiple authentication, in any order)
+ * to gain access to the configuration.
+ */
+struct peer_cfg_t {
+
+ /**
+ * Get the name of the peer_cfg.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @return peer_cfg's name
+ */
+ char* (*get_name) (peer_cfg_t *this);
+
+ /**
+ * Get the IKE version to use for initiating.
+ *
+ * @return IKE major version
+ */
+ u_int (*get_ike_version)(peer_cfg_t *this);
+
+ /**
+ * Get the IKE config to use for initiaton.
+ *
+ * @return the IKE config to use
+ */
+ ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this);
+
+ /**
+ * Attach a CHILD config.
+ *
+ * @param child_cfg CHILD config to add
+ */
+ void (*add_child_cfg) (peer_cfg_t *this, child_cfg_t *child_cfg);
+
+ /**
+ * Detach a CHILD config, pointed to by an enumerator.
+ *
+ * @param enumerator enumerator indicating element position
+ */
+ void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator);
+
+ /**
+ * Create an enumerator for all attached CHILD configs.
+ *
+ * @return an enumerator over all CHILD configs.
+ */
+ enumerator_t* (*create_child_cfg_enumerator) (peer_cfg_t *this);
+
+ /**
+ * Select a CHILD config from traffic selectors.
+ *
+ * @param my_ts TS for local side
+ * @param other_ts TS for remote side
+ * @param my_host host to narrow down dynamic TS for local side
+ * @param other_host host to narrow down dynamic TS for remote side
+ * @return selected CHILD config, or NULL if no match found
+ */
+ child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, linked_list_t *my_ts,
+ linked_list_t *other_ts, host_t *my_host,
+ host_t *other_host);
+
+ /**
+ * Add an authentication config to the peer configuration.
+ *
+ * @param config config to add
+ * @param local TRUE for local rules, FALSE for remote constraints
+ */
+ void (*add_auth_cfg)(peer_cfg_t *this, auth_cfg_t *cfg, bool local);
+
+ /**
+ * Create an enumerator over registered authentication configs.
+ *
+ * @param local TRUE for local rules, FALSE for remote constraints
+ * @return enumerator over auth_cfg_t*
+ */
+ enumerator_t* (*create_auth_cfg_enumerator)(peer_cfg_t *this, bool local);
+
+ /**
+ * Should be sent a certificate for this connection?
+ *
+ * @return certificate sending policy
+ */
+ cert_policy_t (*get_cert_policy) (peer_cfg_t *this);
+
+ /**
+ * How to handle uniqueness of IKE_SAs?
+ *
+ * @return unique policy
+ */
+ unique_policy_t (*get_unique_policy) (peer_cfg_t *this);
+
+ /**
+ * Get the max number of retries after timeout.
+ *
+ * @return max number retries
+ */
+ u_int32_t (*get_keyingtries) (peer_cfg_t *this);
+
+ /**
+ * Get a time to start rekeying (is randomized with jitter).
+ *
+ * @return time in s when to start rekeying, 0 disables rekeying
+ */
+ u_int32_t (*get_rekey_time)(peer_cfg_t *this);
+
+ /**
+ * Get a time to start reauthentication (is randomized with jitter).
+ *
+ * @return time in s when to start reauthentication, 0 disables it
+ */
+ u_int32_t (*get_reauth_time)(peer_cfg_t *this);
+
+ /**
+ * Get the timeout of a rekeying/reauthenticating SA.
+ *
+ * @return timeout in s
+ */
+ u_int32_t (*get_over_time)(peer_cfg_t *this);
+
+ /**
+ * Use MOBIKE (RFC4555) if peer supports it?
+ *
+ * @return TRUE to enable MOBIKE support
+ */
+ bool (*use_mobike) (peer_cfg_t *this);
+
+ /**
+ * Get the DPD check interval.
+ *
+ * @return dpd_delay in seconds
+ */
+ u_int32_t (*get_dpd) (peer_cfg_t *this);
+
+ /**
+ * Get a virtual IP for the local peer.
+ *
+ * If no virtual IP should be used, NULL is returned. %any means to request
+ * a virtual IP using configuration payloads. A specific address is also
+ * used for a request and may be changed by the server.
+ *
+ * @param suggestion NULL, %any or specific
+ * @return virtual IP, %any or NULL
+ */
+ host_t* (*get_virtual_ip) (peer_cfg_t *this);
+
+ /**
+ * Get the name of the pool to acquire configuration attributes from.
+ *
+ * @return pool name, NULL if none defined
+ */
+ char* (*get_pool)(peer_cfg_t *this);
+
+#ifdef ME
+ /**
+ * Is this a mediation connection?
+ *
+ * @return TRUE, if this is a mediation connection
+ */
+ bool (*is_mediation) (peer_cfg_t *this);
+
+ /**
+ * Get peer_cfg of the connection this one is mediated through.
+ *
+ * @return the peer_cfg of the mediation connection
+ */
+ peer_cfg_t* (*get_mediated_by) (peer_cfg_t *this);
+
+ /**
+ * Get the id of the other peer at the mediation server.
+ *
+ * This is the leftid of the peer's connection with the mediation server.
+ *
+ * If it is not configured, it is assumed to be the same as the right id
+ * of this connection.
+ *
+ * @return the id of the other peer
+ */
+ identification_t* (*get_peer_id) (peer_cfg_t *this);
+#endif /* ME */
+
+ /**
+ * Check if two peer configurations are equal.
+ *
+ * This method does not compare associated ike/child_cfg.
+ *
+ * @param other candidate to check for equality against this
+ * @return TRUE if peer_cfg and ike_cfg are equal
+ */
+ bool (*equals)(peer_cfg_t *this, peer_cfg_t *other);
+
+ /**
+ * Increase reference count.
+ *
+ * @return reference to this
+ */
+ peer_cfg_t* (*get_ref) (peer_cfg_t *this);
+
+ /**
+ * Destroys the peer_cfg object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the peer_cfg when it reaches zero.
+ */
+ void (*destroy) (peer_cfg_t *this);
+};
+
+/**
+ * Create a configuration object for IKE_AUTH and later.
+ *
+ * name-string gets cloned, ID's not.
+ * Virtual IPs are used if they are != NULL. A %any host means the virtual
+ * IP should be obtained from the other peer.
+ * Lifetimes are in seconds. To prevent to peers to start rekeying at the
+ * same time, a jitter may be specified. Rekeying of an SA starts at
+ * (rekeylifetime - random(0, jitter)).
+ *
+ * @param name name of the peer_cfg
+ * @param ike_version which IKE version we sould use for this peer
+ * @param ike_cfg IKE config to use when acting as initiator
+ * @param cert_policy should we send a certificate payload?
+ * @param unique uniqueness of an IKE_SA
+ * @param keyingtries how many keying tries should be done before giving up
+ * @param rekey_time timeout before starting rekeying
+ * @param reauth_time timeout before starting reauthentication
+ * @param jitter_time timerange to randomly substract from rekey/reauth time
+ * @param over_time maximum overtime before closing a rekeying/reauth SA
+ * @param mobike use MOBIKE (RFC4555) if peer supports it
+ * @param dpd DPD check interval, 0 to disable
+ * @param virtual_ip virtual IP for local host, or NULL
+ * @param pool pool name to get configuration attributes from, or NULL
+ * @param mediation TRUE if this is a mediation connection
+ * @param mediated_by peer_cfg_t of the mediation connection to mediate through
+ * @param peer_id ID that identifies our peer at the mediation server
+ * @return peer_cfg_t object
+ */
+peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
+ cert_policy_t cert_policy, unique_policy_t unique,
+ u_int32_t keyingtries, u_int32_t rekey_time,
+ u_int32_t reauth_time, u_int32_t jitter_time,
+ u_int32_t over_time, bool mobike, u_int32_t dpd,
+ host_t *virtual_ip, char *pool,
+ bool mediation, peer_cfg_t *mediated_by,
+ identification_t *peer_id);
+
+#endif /** PEER_CFG_H_ @}*/
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
new file mode 100644
index 000000000..e86393028
--- /dev/null
+++ b/src/libcharon/config/proposal.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2006 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 <string.h>
+
+#include "proposal.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <utils/lexparser.h>
+#include <crypto/transform.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <crypto/proposal/proposal_keywords.h>
+
+ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP,
+ "PROTO_NONE",
+ "IKE",
+ "AH",
+ "ESP",
+);
+
+ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
+ "NO_EXT_SEQ",
+ "EXT_SEQ",
+);
+
+typedef struct private_proposal_t private_proposal_t;
+typedef struct algorithm_t algorithm_t;
+
+/**
+ * Private data of an proposal_t object
+ */
+struct private_proposal_t {
+
+ /**
+ * Public part
+ */
+ proposal_t public;
+
+ /**
+ * protocol (ESP or AH)
+ */
+ protocol_id_t protocol;
+
+ /**
+ * priority ordered list of encryption algorithms
+ */
+ linked_list_t *encryption_algos;
+
+ /**
+ * priority ordered list of integrity algorithms
+ */
+ linked_list_t *integrity_algos;
+
+ /**
+ * priority ordered list of pseudo random functions
+ */
+ linked_list_t *prf_algos;
+
+ /**
+ * priority ordered list of dh groups
+ */
+ linked_list_t *dh_groups;
+
+ /**
+ * priority ordered list of extended sequence number flags
+ */
+ linked_list_t *esns;
+
+ /**
+ * senders SPI
+ */
+ u_int64_t spi;
+};
+
+/**
+ * Struct used to store different kinds of algorithms.
+ */
+struct algorithm_t {
+ /**
+ * Value from an encryption_algorithm_t/integrity_algorithm_t/...
+ */
+ u_int16_t algorithm;
+
+ /**
+ * the associated key size in bits, or zero if not needed
+ */
+ u_int16_t key_size;
+};
+
+/**
+ * Add algorithm/keysize to a algorithm list
+ */
+static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size)
+{
+ algorithm_t *algo_key;
+
+ algo_key = malloc_thing(algorithm_t);
+ algo_key->algorithm = algo;
+ algo_key->key_size = key_size;
+ list->insert_last(list, (void*)algo_key);
+}
+
+/**
+ * Implements proposal_t.add_algorithm
+ */
+static void add_algorithm(private_proposal_t *this, transform_type_t type,
+ u_int16_t algo, u_int16_t key_size)
+{
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ add_algo(this->encryption_algos, algo, key_size);
+ break;
+ case INTEGRITY_ALGORITHM:
+ add_algo(this->integrity_algos, algo, key_size);
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ add_algo(this->prf_algos, algo, key_size);
+ break;
+ case DIFFIE_HELLMAN_GROUP:
+ add_algo(this->dh_groups, algo, 0);
+ break;
+ case EXTENDED_SEQUENCE_NUMBERS:
+ add_algo(this->esns, algo, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * filter function for peer configs
+ */
+static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg,
+ void **unused, u_int16_t *key_size)
+{
+ algorithm_t *algo = *in;
+ *alg = algo->algorithm;
+ if (key_size)
+ {
+ *key_size = algo->key_size;
+ }
+ return TRUE;
+}
+
+/**
+ * Implements proposal_t.create_enumerator.
+ */
+static enumerator_t *create_enumerator(private_proposal_t *this,
+ transform_type_t type)
+{
+ linked_list_t *list;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ list = this->encryption_algos;
+ break;
+ case INTEGRITY_ALGORITHM:
+ list = this->integrity_algos;
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ list = this->prf_algos;
+ break;
+ case DIFFIE_HELLMAN_GROUP:
+ list = this->dh_groups;
+ break;
+ case EXTENDED_SEQUENCE_NUMBERS:
+ list = this->esns;
+ break;
+ default:
+ return NULL;
+ }
+ return enumerator_create_filter(list->create_enumerator(list),
+ (void*)alg_filter, NULL, NULL);
+}
+
+/**
+ * Implements proposal_t.get_algorithm.
+ */
+static bool get_algorithm(private_proposal_t *this, transform_type_t type,
+ u_int16_t *alg, u_int16_t *key_size)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+
+ enumerator = create_enumerator(this, type);
+ if (enumerator->enumerate(enumerator, alg, key_size))
+ {
+ found = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Implements proposal_t.has_dh_group
+ */
+static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group)
+{
+ bool result = FALSE;
+
+ if (this->dh_groups->get_count(this->dh_groups))
+ {
+ algorithm_t *current;
+ enumerator_t *enumerator;
+
+ enumerator = this->dh_groups->create_enumerator(this->dh_groups);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->algorithm == group)
+ {
+ result = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else if (group == MODP_NONE)
+ {
+ result = TRUE;
+ }
+ return result;
+}
+
+/**
+ * Implementation of proposal_t.strip_dh.
+ */
+static void strip_dh(private_proposal_t *this)
+{
+ algorithm_t *alg;
+
+ while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS)
+ {
+ free(alg);
+ }
+}
+
+/**
+ * Returns true if the given alg is an authenticated encryption algorithm
+ */
+static bool is_authenticated_encryption(u_int16_t alg)
+{
+ switch(alg)
+ {
+ 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:
+ case ENCR_NULL_AUTH_AES_GMAC:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Find a matching alg/keysize in two linked lists
+ */
+static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv,
+ bool *add, u_int16_t *alg, size_t *key_size)
+{
+ enumerator_t *e1, *e2;
+ algorithm_t *alg1, *alg2;
+
+ /* if in both are zero algorithms specified, we HAVE a match */
+ if (first->get_count(first) == 0 && second->get_count(second) == 0)
+ {
+ *add = FALSE;
+ return TRUE;
+ }
+
+ e1 = first->create_enumerator(first);
+ e2 = second->create_enumerator(second);
+ /* compare algs, order of algs in "first" is preferred */
+ while (e1->enumerate(e1, &alg1))
+ {
+ e2->destroy(e2);
+ e2 = second->create_enumerator(second);
+ while (e2->enumerate(e2, &alg2))
+ {
+ if (alg1->algorithm == alg2->algorithm &&
+ alg1->key_size == alg2->key_size)
+ {
+ if (!priv && alg1->algorithm >= 1024)
+ {
+ /* accept private use algorithms only if requested */
+ DBG1(DBG_CFG, "an algorithm from private space would match, "
+ "but peer implementation is unknown, skipped");
+ continue;
+ }
+ /* ok, we have an algorithm */
+ *alg = alg1->algorithm;
+ *key_size = alg1->key_size;
+ *add = TRUE;
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return TRUE;
+ }
+ }
+ }
+ /* no match in all comparisons */
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return FALSE;
+}
+
+/**
+ * Implements proposal_t.select.
+ */
+static proposal_t *select_proposal(private_proposal_t *this,
+ private_proposal_t *other, bool private)
+{
+ proposal_t *selected;
+ u_int16_t algo;
+ size_t key_size;
+ bool add;
+
+ DBG2(DBG_CFG, "selecting proposal:");
+
+ /* check protocol */
+ if (this->protocol != other->protocol)
+ {
+ DBG2(DBG_CFG, " protocol mismatch, skipping");
+ return NULL;
+ }
+
+ selected = proposal_create(this->protocol);
+
+ /* select encryption algorithm */
+ if (select_algo(this->encryption_algos, other->encryption_algos, private,
+ &add, &algo, &key_size))
+ {
+ if (add)
+ {
+ selected->add_algorithm(selected, ENCRYPTION_ALGORITHM,
+ algo, key_size);
+ }
+ }
+ else
+ {
+ selected->destroy(selected);
+ DBG2(DBG_CFG, " no acceptable %N found",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ return NULL;
+ }
+ /* select integrity algorithm */
+ if (!is_authenticated_encryption(algo))
+ {
+ if (select_algo(this->integrity_algos, other->integrity_algos, private,
+ &add, &algo, &key_size))
+ {
+ if (add)
+ {
+ selected->add_algorithm(selected, INTEGRITY_ALGORITHM,
+ algo, key_size);
+ }
+ }
+ else
+ {
+ selected->destroy(selected);
+ DBG2(DBG_CFG, " no acceptable %N found",
+ transform_type_names, INTEGRITY_ALGORITHM);
+ return NULL;
+ }
+ }
+ /* select prf algorithm */
+ if (select_algo(this->prf_algos, other->prf_algos, private,
+ &add, &algo, &key_size))
+ {
+ if (add)
+ {
+ selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION,
+ algo, key_size);
+ }
+ }
+ else
+ {
+ selected->destroy(selected);
+ DBG2(DBG_CFG, " no acceptable %N found",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return NULL;
+ }
+ /* select a DH-group */
+ if (select_algo(this->dh_groups, other->dh_groups, private,
+ &add, &algo, &key_size))
+ {
+ if (add)
+ {
+ selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0);
+ }
+ }
+ else
+ {
+ selected->destroy(selected);
+ DBG2(DBG_CFG, " no acceptable %N found",
+ transform_type_names, DIFFIE_HELLMAN_GROUP);
+ return NULL;
+ }
+ /* select if we use ESNs (has no private use space) */
+ if (select_algo(this->esns, other->esns, TRUE, &add, &algo, &key_size))
+ {
+ if (add)
+ {
+ selected->add_algorithm(selected, EXTENDED_SEQUENCE_NUMBERS, algo, 0);
+ }
+ }
+ else
+ {
+ selected->destroy(selected);
+ DBG2(DBG_CFG, " no acceptable %N found",
+ transform_type_names, EXTENDED_SEQUENCE_NUMBERS);
+ return NULL;
+ }
+ DBG2(DBG_CFG, " proposal matches");
+
+ /* apply SPI from "other" */
+ selected->set_spi(selected, other->spi);
+
+ /* everything matched, return new proposal */
+ return selected;
+}
+
+/**
+ * Implements proposal_t.get_protocols.
+ */
+static protocol_id_t get_protocol(private_proposal_t *this)
+{
+ return this->protocol;
+}
+
+/**
+ * Implements proposal_t.set_spi.
+ */
+static void set_spi(private_proposal_t *this, u_int64_t spi)
+{
+ this->spi = spi;
+}
+
+/**
+ * Implements proposal_t.get_spi.
+ */
+static u_int64_t get_spi(private_proposal_t *this)
+{
+ return this->spi;
+}
+
+/**
+ * Clone a algorithm list
+ */
+static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
+{
+ algorithm_t *algo, *clone_algo;
+ enumerator_t *enumerator;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &algo))
+ {
+ clone_algo = malloc_thing(algorithm_t);
+ memcpy(clone_algo, algo, sizeof(algorithm_t));
+ clone_list->insert_last(clone_list, (void*)clone_algo);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * check if an algorithm list equals
+ */
+static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
+{
+ enumerator_t *e1, *e2;
+ algorithm_t *alg1, *alg2;
+ bool equals = TRUE;
+
+ if (l1->get_count(l1) != l2->get_count(l2))
+ {
+ return FALSE;
+ }
+
+ e1 = l1->create_enumerator(l1);
+ e2 = l2->create_enumerator(l2);
+ while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2))
+ {
+ if (alg1->algorithm != alg2->algorithm ||
+ alg1->key_size != alg2->key_size)
+ {
+ equals = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return equals;
+}
+
+/**
+ * Implementation of proposal_t.equals.
+ */
+static bool equals(private_proposal_t *this, private_proposal_t *other)
+{
+ if (this == other)
+ {
+ return TRUE;
+ }
+ if (this->public.equals != other->public.equals)
+ {
+ return FALSE;
+ }
+ return (
+ algo_list_equals(this->encryption_algos, other->encryption_algos) &&
+ algo_list_equals(this->integrity_algos, other->integrity_algos) &&
+ algo_list_equals(this->prf_algos, other->prf_algos) &&
+ algo_list_equals(this->dh_groups, other->dh_groups) &&
+ algo_list_equals(this->esns, other->esns));
+}
+
+/**
+ * Implements proposal_t.clone
+ */
+static proposal_t *clone_(private_proposal_t *this)
+{
+ private_proposal_t *clone = (private_proposal_t*)proposal_create(this->protocol);
+
+ clone_algo_list(this->encryption_algos, clone->encryption_algos);
+ clone_algo_list(this->integrity_algos, clone->integrity_algos);
+ clone_algo_list(this->prf_algos, clone->prf_algos);
+ clone_algo_list(this->dh_groups, clone->dh_groups);
+ clone_algo_list(this->esns, clone->esns);
+
+ clone->spi = this->spi;
+
+ return &clone->public;
+}
+
+/**
+ * Checks the proposal read from a string.
+ */
+static void check_proposal(private_proposal_t *this)
+{
+ enumerator_t *e;
+ algorithm_t *alg;
+ bool all_aead = TRUE;
+
+ e = this->encryption_algos->create_enumerator(this->encryption_algos);
+ while (e->enumerate(e, &alg))
+ {
+ if (!is_authenticated_encryption(alg->algorithm))
+ {
+ all_aead = FALSE;
+ break;
+ }
+ }
+ e->destroy(e);
+
+ if (all_aead)
+ {
+ /* if all encryption algorithms in the proposal are authenticated encryption
+ * algorithms we MUST NOT propose any integrity algorithms */
+ while (this->integrity_algos->remove_last(this->integrity_algos,
+ (void**)&alg) == SUCCESS)
+ {
+ free(alg);
+ }
+ }
+}
+
+/**
+ * add a algorithm identified by a string to the proposal.
+ */
+static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
+{
+ const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
+
+ if (token == NULL)
+ {
+ return FAILED;
+ }
+
+ add_algorithm(this, token->type, token->algorithm, token->keysize);
+
+ if (this->protocol == PROTO_IKE && token->type == INTEGRITY_ALGORITHM)
+ {
+ pseudo_random_function_t prf;
+
+ switch (token->algorithm)
+ {
+ case AUTH_HMAC_SHA1_96:
+ prf = PRF_HMAC_SHA1;
+ break;
+ case AUTH_HMAC_SHA2_256_128:
+ prf = PRF_HMAC_SHA2_256;
+ break;
+ case AUTH_HMAC_SHA2_384_192:
+ prf = PRF_HMAC_SHA2_384;
+ break;
+ case AUTH_HMAC_SHA2_512_256:
+ prf = PRF_HMAC_SHA2_512;
+ break;
+ case AUTH_HMAC_MD5_96:
+ prf = PRF_HMAC_MD5;
+ break;
+ case AUTH_AES_XCBC_96:
+ prf = PRF_AES128_XCBC;
+ break;
+ default:
+ prf = PRF_UNDEFINED;
+ }
+ if (prf != PRF_UNDEFINED)
+ {
+ add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ }
+ }
+ return SUCCESS;
+}
+
+/**
+ * print all algorithms of a kind to buffer
+ */
+static int print_alg(private_proposal_t *this, char **dst, size_t *len,
+ u_int kind, void *names, bool *first)
+{
+ enumerator_t *enumerator;
+ size_t written = 0;
+ u_int16_t alg, size;
+
+ enumerator = create_enumerator(this, kind);
+ while (enumerator->enumerate(enumerator, &alg, &size))
+ {
+ if (*first)
+ {
+ written += print_in_hook(*dst, *len, "%N", names, alg);
+ *first = FALSE;
+ }
+ else
+ {
+ written += print_in_hook(*dst, *len, "/%N", names, alg);
+ }
+ if (size)
+ {
+ written += print_in_hook(*dst, *len, "_%u", size);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return written;
+}
+
+/**
+ * Described in header.
+ */
+int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ private_proposal_t *this = *((private_proposal_t**)(args[0]));
+ linked_list_t *list = *((linked_list_t**)(args[0]));
+ enumerator_t *enumerator;
+ size_t written = 0;
+ bool first = TRUE;
+
+ if (this == NULL)
+ {
+ return print_in_hook(dst, len, "(null)");
+ }
+
+ if (spec->hash)
+ {
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &this))
+ { /* call recursivly */
+ if (first)
+ {
+ written += print_in_hook(dst, len, "%P", this);
+ first = FALSE;
+ }
+ else
+ {
+ written += print_in_hook(dst, len, ", %P", this);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return written;
+ }
+
+ written = print_in_hook(dst, len, "%N:", protocol_id_names, this->protocol);
+ written += print_alg(this, &dst, &len, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, &first);
+ written += print_alg(this, &dst, &len, INTEGRITY_ALGORITHM,
+ integrity_algorithm_names, &first);
+ written += print_alg(this, &dst, &len, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, &first);
+ written += print_alg(this, &dst, &len, DIFFIE_HELLMAN_GROUP,
+ diffie_hellman_group_names, &first);
+ written += print_alg(this, &dst, &len, EXTENDED_SEQUENCE_NUMBERS,
+ extended_sequence_numbers_names, &first);
+ return written;
+}
+
+/**
+ * Implements proposal_t.destroy.
+ */
+static void destroy(private_proposal_t *this)
+{
+ this->encryption_algos->destroy_function(this->encryption_algos, free);
+ this->integrity_algos->destroy_function(this->integrity_algos, free);
+ this->prf_algos->destroy_function(this->prf_algos, free);
+ this->dh_groups->destroy_function(this->dh_groups, free);
+ this->esns->destroy_function(this->esns, free);
+ free(this);
+}
+
+/*
+ * Describtion in header-file
+ */
+proposal_t *proposal_create(protocol_id_t protocol)
+{
+ private_proposal_t *this = malloc_thing(private_proposal_t);
+
+ this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm;
+ this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator;
+ this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm;
+ this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group;
+ this->public.strip_dh = (void(*)(proposal_t*))strip_dh;
+ this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*,bool))select_proposal;
+ this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol;
+ this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi;
+ this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi;
+ this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals;
+ this->public.clone = (proposal_t*(*)(proposal_t*))clone_;
+ this->public.destroy = (void(*)(proposal_t*))destroy;
+
+ this->spi = 0;
+ this->protocol = protocol;
+
+ this->encryption_algos = linked_list_create();
+ this->integrity_algos = linked_list_create();
+ this->prf_algos = linked_list_create();
+ this->dh_groups = linked_list_create();
+ this->esns = linked_list_create();
+
+ return &this->public;
+}
+
+/**
+ * Add supported IKE algorithms to proposal
+ */
+static void proposal_add_supported_ike(private_proposal_t *this)
+{
+ enumerator_t *enumerator;
+ encryption_algorithm_t encryption;
+ integrity_algorithm_t integrity;
+ pseudo_random_function_t prf;
+ diffie_hellman_group_t group;
+
+ enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &encryption))
+ {
+ switch (encryption)
+ {
+ case ENCR_AES_CBC:
+ /* we assume that we support all AES 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:
+ case ENCR_AES_CTR:
+ 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:
+ add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
+ break;
+ case ENCR_DES:
+ /* no, thanks */
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &integrity))
+ {
+ 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:
+ add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &prf))
+ {
+ switch (prf)
+ {
+ case PRF_HMAC_SHA1:
+ case PRF_HMAC_SHA2_256:
+ case PRF_HMAC_SHA2_384:
+ case PRF_HMAC_SHA2_512:
+ case PRF_HMAC_MD5:
+ case PRF_AES128_XCBC:
+ add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &group))
+ {
+ switch (group)
+ {
+ case MODP_NULL:
+ /* only for testing purposes */
+ break;
+ case MODP_768_BIT:
+ /* weak */
+ break;
+ case MODP_1024_BIT:
+ case MODP_1536_BIT:
+ case MODP_2048_BIT:
+ case MODP_4096_BIT:
+ case MODP_8192_BIT:
+ case ECP_256_BIT:
+ case ECP_384_BIT:
+ case ECP_521_BIT:
+ case MODP_1024_160:
+ case MODP_2048_224:
+ case MODP_2048_256:
+ case ECP_192_BIT:
+ case ECP_224_BIT:
+ add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/*
+ * Describtion in header-file
+ */
+proposal_t *proposal_create_default(protocol_id_t protocol)
+{
+ private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+
+ switch (protocol)
+ {
+ case PROTO_IKE:
+ proposal_add_supported_ike(this);
+ break;
+ case PROTO_ESP:
+ add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
+ add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
+ add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
+ add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
+ add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+ add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+ break;
+ case PROTO_AH:
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
+ add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+ add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+ break;
+ default:
+ break;
+ }
+ return &this->public;
+}
+
+/*
+ * Describtion in header-file
+ */
+proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
+{
+ private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+ chunk_t string = {(void*)algs, strlen(algs)};
+ chunk_t alg;
+ status_t status = SUCCESS;
+
+ eat_whitespace(&string);
+ if (string.len < 1)
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ /* get all tokens, separated by '-' */
+ while (extract_token(&alg, '-', &string))
+ {
+ status |= add_string_algo(this, alg);
+ }
+ if (string.len)
+ {
+ status |= add_string_algo(this, string);
+ }
+ if (status != SUCCESS)
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ check_proposal(this);
+
+ if (protocol == PROTO_AH || protocol == PROTO_ESP)
+ {
+ add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h
new file mode 100644
index 000000000..30f63b80d
--- /dev/null
+++ b/src/libcharon/config/proposal.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2006 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 proposal proposal
+ * @{ @ingroup config
+ */
+
+#ifndef PROPOSAL_H_
+#define PROPOSAL_H_
+
+typedef enum protocol_id_t protocol_id_t;
+typedef enum extended_sequence_numbers_t extended_sequence_numbers_t;
+typedef struct proposal_t proposal_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <utils/linked_list.h>
+#include <utils/host.h>
+#include <crypto/transform.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <crypto/diffie_hellman.h>
+#include <selectors/traffic_selector.h>
+
+/**
+ * Protocol ID of a proposal.
+ */
+enum protocol_id_t {
+ PROTO_NONE = 0,
+ PROTO_IKE = 1,
+ PROTO_AH = 2,
+ PROTO_ESP = 3,
+};
+
+/**
+ * enum names for protocol_id_t
+ */
+extern enum_name_t *protocol_id_names;
+
+/**
+ * Extended sequence numbers, as in IKEv2 RFC 3.3.2.
+ */
+enum extended_sequence_numbers_t {
+ NO_EXT_SEQ_NUMBERS = 0,
+ EXT_SEQ_NUMBERS = 1
+};
+
+/**
+ * enum strings for extended_sequence_numbers_t.
+ */
+extern enum_name_t *extended_sequence_numbers_names;
+
+/**
+ * Stores a set of algorithms used for an SA.
+ *
+ * A proposal stores algorithms for a specific
+ * protocol. It can store algorithms for one protocol.
+ * Proposals with multiple protocols are not supported,
+ * as it's not specified in RFC4301 anymore.
+ */
+struct proposal_t {
+
+ /**
+ * Add an algorithm to the proposal.
+ *
+ * The algorithms are stored by priority, first added
+ * is the most preferred.
+ * Key size is only needed for encryption algorithms
+ * with variable key size (such as AES). Must be set
+ * to zero if key size is not specified.
+ * The alg parameter accepts encryption_algorithm_t,
+ * integrity_algorithm_t, dh_group_number_t and
+ * extended_sequence_numbers_t.
+ *
+ * @param type kind of algorithm
+ * @param alg identifier for algorithm
+ * @param key_size key size to use
+ */
+ void (*add_algorithm) (proposal_t *this, transform_type_t type,
+ u_int16_t alg, u_int16_t key_size);
+
+ /**
+ * Get an enumerator over algorithms for a specifc algo type.
+ *
+ * @param type kind of algorithm
+ * @return enumerator over u_int16_t alg, u_int16_t key_size
+ */
+ enumerator_t *(*create_enumerator) (proposal_t *this, transform_type_t type);
+
+ /**
+ * Get the algorithm for a type to use.
+ *
+ * If there are multiple algorithms, only the first is returned.
+ *
+ * @param type kind of algorithm
+ * @param alg pointer which receives algorithm
+ * @param key_size pointer which receives the key size
+ * @return TRUE if algorithm of this kind available
+ */
+ bool (*get_algorithm) (proposal_t *this, transform_type_t type,
+ u_int16_t *alg, u_int16_t *key_size);
+
+ /**
+ * Check if the proposal has a specific DH group.
+ *
+ * @param group group to check for
+ * @return TRUE if algorithm included
+ */
+ bool (*has_dh_group) (proposal_t *this, diffie_hellman_group_t group);
+
+ /**
+ * Strip DH groups from proposal to use it without PFS.
+ */
+ void (*strip_dh)(proposal_t *this);
+
+ /**
+ * Compare two proposal, and select a matching subset.
+ *
+ * If the proposals are for the same protocols (AH/ESP), they are
+ * compared. If they have at least one algorithm of each type
+ * in common, a resulting proposal of this kind is created.
+ *
+ * @param other proposal to compair agains
+ * @param private accepts algorithms allocated in a private range
+ * @return selected proposal, NULL if proposals don't match
+ */
+ proposal_t *(*select) (proposal_t *this, proposal_t *other, bool private);
+
+ /**
+ * Get the protocol ID of the proposal.
+ *
+ * @return protocol of the proposal
+ */
+ protocol_id_t (*get_protocol) (proposal_t *this);
+
+ /**
+ * Get the SPI of the proposal.
+ *
+ * @return spi for proto
+ */
+ u_int64_t (*get_spi) (proposal_t *this);
+
+ /**
+ * Set the SPI of the proposal.
+ *
+ * @param spi spi to set for proto
+ */
+ void (*set_spi) (proposal_t *this, u_int64_t spi);
+
+ /**
+ * Check for the eqality of two proposals.
+ *
+ * @param other other proposal to check for equality
+ * @return TRUE if other equal to this
+ */
+ bool (*equals)(proposal_t *this, proposal_t *other);
+
+ /**
+ * Clone a proposal.
+ *
+ * @return clone of proposal
+ */
+ proposal_t *(*clone) (proposal_t *this);
+
+ /**
+ * Destroys the proposal object.
+ */
+ void (*destroy) (proposal_t *this);
+};
+
+/**
+ * Create a child proposal for AH, ESP or IKE.
+ *
+ * @param protocol protocol, such as PROTO_ESP
+ * @return proposal_t object
+ */
+proposal_t *proposal_create(protocol_id_t protocol);
+
+/**
+ * Create a default proposal if nothing further specified.
+ *
+ * @param protocol protocol, such as PROTO_ESP
+ * @return proposal_t object
+ */
+proposal_t *proposal_create_default(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.
+ * E.g.: aes128-sha2_256-modp2048
+ * 3des-md5
+ * An additional '!' at the end of the string forces this proposal,
+ * without it the peer may choose another algorithm we support.
+ *
+ * @param protocol protocol, such as PROTO_ESP
+ * @param algs algorithms as string
+ * @return proposal_t object
+ */
+proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs);
+
+/**
+ * printf hook function for proposal_t.
+ *
+ * Arguments are:
+ * proposal_t *proposal
+ * With the #-specifier, arguments are:
+ * linked_list_t *list containing proposal_t*
+ */
+int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** PROPOSAL_H_ @}*/
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
new file mode 100644
index 000000000..94c64028c
--- /dev/null
+++ b/src/libcharon/control/controller.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "controller.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+#include <daemon.h>
+#include <library.h>
+
+
+typedef struct private_controller_t private_controller_t;
+typedef struct interface_listener_t interface_listener_t;
+
+/**
+ * Private data of an stroke_t object.
+ */
+struct private_controller_t {
+
+ /**
+ * Public part of stroke_t object.
+ */
+ controller_t public;
+};
+
+/**
+ * helper struct to map listener callbacks to interface callbacks
+ */
+struct interface_listener_t {
+
+ /**
+ * public bus listener interface
+ */
+ listener_t public;
+
+ /**
+ * status of the operation, return to method callers
+ */
+ status_t status;
+
+ /**
+ * interface callback (listener gets redirected to here)
+ */
+ controller_cb_t callback;
+
+ /**
+ * user parameter to pass to callback
+ */
+ void *param;
+
+ /**
+ * child configuration, used for initiate
+ */
+ child_cfg_t *child_cfg;
+
+ /**
+ * peer configuration, used for initiate
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * IKE_SA to handle
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * CHILD_SA to handle
+ */
+ child_sa_t *child_sa;
+
+ /**
+ * unique ID, used for various methods
+ */
+ u_int32_t id;
+};
+
+
+typedef struct interface_job_t interface_job_t;
+
+/**
+ * job for asynchronous listen operations
+ */
+struct interface_job_t {
+ /**
+ * job interface
+ */
+ job_t public;
+
+ /**
+ * associated listener
+ */
+ interface_listener_t listener;
+};
+
+/**
+ * listener log function
+ */
+static bool listener_log(interface_listener_t *this, debug_t group,
+ level_t level, int thread, ike_sa_t *ike_sa,
+ char* format, va_list args)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ if (!this->callback(this->param, group, level, ike_sa, format, args))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool listener_ike_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ switch (state)
+ {
+#ifdef ME
+ case IKE_ESTABLISHED:
+ { /* mediation connections are complete without CHILD_SA */
+ peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ this->status = SUCCESS;
+ return FALSE;
+ }
+ break;
+ }
+#endif /* ME */
+ case IKE_DESTROYING:
+ if (ike_sa->get_state(ike_sa) == IKE_DELETING)
+ { /* proper termination */
+ this->status = SUCCESS;
+ }
+ return FALSE;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool listener_child_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ switch (state)
+ {
+ case CHILD_INSTALLED:
+ this->status = SUCCESS;
+ return FALSE;
+ case CHILD_DESTROYING:
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_DELETING:
+ /* proper delete */
+ this->status = SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * cleanup job if job is never executed
+ */
+static void recheckin(interface_job_t *job)
+{
+ if (job->listener.ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ job->listener.ike_sa);
+ }
+}
+
+/**
+ * Implementation of controller_t.create_ike_sa_iterator.
+ */
+static enumerator_t* create_ike_sa_enumerator(controller_t *this)
+{
+ return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+}
+
+/**
+ * execute function for initiate
+ */
+static status_t initiate_execute(interface_job_t *job)
+{
+ ike_sa_t *ike_sa;
+ interface_listener_t *listener = &job->listener;
+ peer_cfg_t *peer_cfg = listener->peer_cfg;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
+ listener->ike_sa = ike_sa;
+
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ }
+ peer_cfg->destroy(peer_cfg);
+
+ if (ike_sa->initiate(ike_sa, listener->child_cfg, 0, NULL, NULL) == SUCCESS)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return SUCCESS;
+ }
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ return FAILED;
+}
+
+/**
+ * Implementation of controller_t.initiate.
+ */
+static status_t initiate(private_controller_t *this,
+ peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
+ controller_cb_t callback, void *param)
+{
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .child_cfg = child_cfg,
+ .peer_cfg = peer_cfg,
+ },
+ .public = {
+ .execute = (void*)initiate_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
+ if (callback == NULL)
+ {
+ return initiate_execute(&job);
+ }
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
+ return job.listener.status;
+}
+
+/**
+ * execute function for terminate_ike
+ */
+static status_t terminate_ike_execute(interface_job_t *job)
+{
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+
+ if (ike_sa->delete(ike_sa) != DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ /* delete failed */
+ return FAILED;
+ }
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of controller_t.terminate_ike.
+ */
+static status_t terminate_ike(controller_t *this, u_int32_t unique_id,
+ controller_cb_t callback, void *param)
+{
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = unique_id,
+ },
+ .public = {
+ .execute = (void*)terminate_ike_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ unique_id, FALSE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
+
+ if (callback == NULL)
+ {
+ return terminate_ike_execute(&job);
+ }
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
+ return job.listener.status;
+}
+
+/**
+ * execute function for terminate_child
+ */
+static status_t terminate_child_execute(interface_job_t *job)
+{
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+ child_sa_t *child_sa = listener->child_sa;
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE)) != DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return SUCCESS;
+ }
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ return FAILED;
+}
+
+/**
+ * Implementation of controller_t.terminate_child.
+ */
+static status_t terminate_child(controller_t *this, u_int32_t reqid,
+ controller_cb_t callback, void *param)
+{
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ iterator_t *iterator;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = reqid,
+ },
+ .public = {
+ .execute = (void*)terminate_child_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found",
+ reqid);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
+
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ if (child_sa->get_state(child_sa) != CHILD_ROUTED &&
+ child_sa->get_reqid(child_sa) == reqid)
+ {
+ break;
+ }
+ child_sa = NULL;
+ }
+ iterator->destroy(iterator);
+
+ if (child_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to terminate, established "
+ "CHILD_SA with ID %d not found", reqid);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return NOT_FOUND;
+ }
+ job.listener.child_sa = child_sa;
+
+ if (callback == NULL)
+ {
+ return terminate_child_execute(&job);
+ }
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
+ return job.listener.status;
+}
+
+/**
+ * See header
+ */
+bool controller_cb_empty(void *param, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args)
+{
+ return TRUE;
+}
+
+/**
+ * Implementation of stroke_t.destroy.
+ */
+static void destroy(private_controller_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header-file
+ */
+controller_t *controller_create(void)
+{
+ private_controller_t *this = malloc_thing(private_controller_t);
+
+ this->public.create_ike_sa_enumerator = (enumerator_t*(*)(controller_t*))create_ike_sa_enumerator;
+ this->public.initiate = (status_t(*)(controller_t*,peer_cfg_t*,child_cfg_t*,controller_cb_t,void*))initiate;
+ this->public.terminate_ike = (status_t(*)(controller_t*,u_int32_t,controller_cb_t, void*))terminate_ike;
+ this->public.terminate_child = (status_t(*)(controller_t*,u_int32_t,controller_cb_t, void *param))terminate_child;
+ this->public.destroy = (void (*)(controller_t*))destroy;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
new file mode 100644
index 000000000..31b69c78c
--- /dev/null
+++ b/src/libcharon/control/controller.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup controller_i controller
+ * @{ @ingroup control
+ */
+
+#ifndef CONTROLLER_H_
+#define CONTROLLER_H_
+
+#include <bus/bus.h>
+
+/**
+ * callback to log things triggered by controller.
+ *
+ * @param param echoed parameter supplied when function invoked
+ * @param group debugging group
+ * @param level verbosity level if log
+ * @param ike_sa associated IKE_SA, if any
+ * @param format printf like format string
+ * @param args list of arguments to use for format
+ * @return FALSE to return from invoked function
+ */
+typedef bool(*controller_cb_t)(void* param, debug_t group, level_t level,
+ ike_sa_t* ike_sa, char* format, va_list args);
+
+/**
+ * Empty callback function for controller_t functions.
+ *
+ * If you want to do a synchronous call, but don't need a callback, pass
+ * this function to the controllers methods.
+ */
+bool controller_cb_empty(void *param, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args);
+
+typedef struct controller_t controller_t;
+
+/**
+ * The controller provides a simple interface to run actions.
+ *
+ * The controller starts actions by creating jobs. It then tries to
+ * evaluate the result of the operation by listening on the bus.
+ *
+ * Passing NULL as callback to the managers function calls them asynchronously.
+ * If a callback is specified, they are called synchronously. There is a default
+ * callback "controller_cb_empty" if you wan't to call a function
+ * synchronously, but don't need a callback.
+ */
+struct controller_t {
+
+ /**
+ * Create an enumerator for all IKE_SAs.
+ *
+ * The enumerator blocks the IKE_SA manager until it gets destroyed. Do
+ * not call another interface/manager method while the iterator is alive.
+ *
+ * @return enumerator, locks IKE_SA manager until destroyed
+ */
+ enumerator_t* (*create_ike_sa_enumerator)(controller_t *this);
+
+ /**
+ * Initiate a CHILD_SA, and if required, an IKE_SA.
+ *
+ * The initiate() function is synchronous and thus blocks until the
+ * IKE_SA is established or failed. Because of this, the initiate() function
+ * contains a thread cancellation point.
+ *
+ * @param peer_cfg peer_cfg to use for IKE_SA setup
+ * @param child_cfg child_cfg to set up CHILD_SA from
+ * @param cb logging callback
+ * @param param parameter to include in each call of cb
+ * @return
+ * - SUCCESS, if CHILD_SA established
+ * - FAILED, if setup failed
+ * - NEED_MORE, if callback returned FALSE
+ */
+ status_t (*initiate)(controller_t *this,
+ peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
+ controller_cb_t callback, void *param);
+
+ /**
+ * Terminate an IKE_SA and all of its CHILD_SAs.
+ *
+ * The terminate() function is synchronous and thus blocks until the
+ * IKE_SA is properly deleted, or the delete timed out.
+ * The terminate() function contains a thread cancellation point.
+ *
+ * @param unique_id unique id of the IKE_SA to terminate.
+ * @param cb logging callback
+ * @param param parameter to include in each call of cb
+ * @return
+ * - SUCCESS, if CHILD_SA terminated
+ * - NOT_FOUND, if no such CHILD_SA found
+ * - NEED_MORE, if callback returned FALSE
+ */
+ status_t (*terminate_ike)(controller_t *this, u_int32_t unique_id,
+ controller_cb_t callback, void *param);
+
+ /**
+ * Terminate a CHILD_SA.
+ *
+ * @param reqid reqid of the CHILD_SA to terminate
+ * @param cb logging callback
+ * @param param parameter to include in each call of cb
+ * @return
+ * - SUCCESS, if CHILD_SA terminated
+ * - NOT_FOUND, if no such CHILD_SA found
+ * - NEED_MORE, if callback returned FALSE
+ */
+ status_t (*terminate_child)(controller_t *this, u_int32_t reqid,
+ controller_cb_t callback, void *param);
+
+ /**
+ * Destroy a controller_t instance.
+ */
+ void (*destroy) (controller_t *this);
+};
+
+
+/**
+ * Creates a controller instance.
+ *
+ * @return controller_t object
+ */
+controller_t *controller_create(void);
+
+#endif /** CONTROLLER_H_ @}*/
diff --git a/src/libcharon/credentials/credential_manager.c b/src/libcharon/credentials/credential_manager.c
new file mode 100644
index 000000000..adea0b4be
--- /dev/null
+++ b/src/libcharon/credentials/credential_manager.c
@@ -0,0 +1,1681 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "credential_manager.h"
+
+#include <daemon.h>
+#include <threading/thread_value.h>
+#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+#include <credentials/sets/cert_cache.h>
+#include <credentials/sets/auth_cfg_wrapper.h>
+#include <credentials/sets/ocsp_response_wrapper.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/ocsp_request.h>
+#include <credentials/certificates/ocsp_response.h>
+
+typedef struct private_credential_manager_t private_credential_manager_t;
+
+/**
+ * private data of credential_manager
+ */
+struct private_credential_manager_t {
+
+ /**
+ * public functions
+ */
+ credential_manager_t public;
+
+ /**
+ * list of credential sets
+ */
+ linked_list_t *sets;
+
+ /**
+ * thread local set of credentials, linked_list_t with credential_set_t's
+ */
+ thread_value_t *local_sets;
+
+ /**
+ * trust relationship and certificate cache
+ */
+ cert_cache_t *cache;
+
+ /**
+ * certificates queued for persistent caching
+ */
+ linked_list_t *cache_queue;
+
+ /**
+ * read-write lock to sets list
+ */
+ rwlock_t *lock;
+
+ /**
+ * mutex for cache queue
+ */
+ mutex_t *queue_mutex;
+};
+
+/** data to pass to create_private_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ key_type_t type;
+ identification_t* keyid;
+} private_data_t;
+
+/** data to pass to create_cert_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ certificate_type_t cert;
+ key_type_t key;
+ identification_t *id;
+ bool trusted;
+} cert_data_t;
+
+/** data to pass to create_cdp_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ certificate_type_t type;
+ identification_t *id;
+} cdp_data_t;
+
+/** data to pass to create_shared_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ shared_key_type_t type;
+ identification_t *me;
+ identification_t *other;
+} shared_data_t;
+
+/** enumerator over local and global sets */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over global sets */
+ enumerator_t *global;
+ /** enumerator over local sets */
+ enumerator_t *local;
+} sets_enumerator_t;
+
+/**
+ * destroy a sets_enumerator_t
+ */
+static void sets_enumerator_destroy(sets_enumerator_t *this)
+{
+ DESTROY_IF(this->global);
+ DESTROY_IF(this->local);
+ free(this);
+}
+
+/**
+ * sets_enumerator_t.enumerate
+ */
+static bool sets_enumerator_enumerate(sets_enumerator_t *this,
+ credential_set_t **set)
+{
+ if (this->global)
+ {
+ if (this->global->enumerate(this->global, set))
+ {
+ return TRUE;
+ }
+ /* end of global sets, look for local */
+ this->global->destroy(this->global);
+ this->global = NULL;
+ }
+ if (this->local)
+ {
+ return this->local->enumerate(this->local, set);
+ }
+ return FALSE;
+}
+
+/**
+ * create an enumerator over both, global and local sets
+ */
+static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
+{
+ linked_list_t *local;
+ sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t);
+
+ enumerator->public.enumerate = (void*)sets_enumerator_enumerate;
+ enumerator->public.destroy = (void*)sets_enumerator_destroy;
+ enumerator->global = this->sets->create_enumerator(this->sets);
+ enumerator->local = NULL;
+ local = this->local_sets->get(this->local_sets);
+ if (local)
+ {
+ enumerator->local = local->create_enumerator(local);
+ }
+ return &enumerator->public;
+}
+
+/**
+ * cleanup function for cert data
+ */
+static void destroy_cert_data(cert_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for certificates
+ */
+static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
+{
+ return set->create_cert_enumerator(set, data->cert, data->key,
+ data->id, data->trusted);
+}
+
+/**
+ * Implementation of credential_manager_t.create_cert_enumerator.
+ */
+static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
+ certificate_type_t certificate, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_data_t *data = malloc_thing(cert_data_t);
+ data->this = this;
+ data->cert = certificate;
+ data->key = key;
+ data->id = id;
+ data->trusted = trusted;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_cert, data,
+ (void*)destroy_cert_data);
+}
+
+/**
+ * Implementation of credential_manager_t.get_cert.
+ */
+static certificate_t *get_cert(private_credential_manager_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ certificate_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_cert_enumerator(this, cert, key, id, trusted);
+ if (enumerator->enumerate(enumerator, &current))
+ {
+ /* TODO: best match? order by keyid, subject, sualtname */
+ found = current->get_ref(current);
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+
+/**
+ * cleanup function for cdp data
+ */
+static void destroy_cdp_data(cdp_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for CDPs
+ */
+static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
+{
+ return set->create_cdp_enumerator(set, data->type, data->id);
+}
+/**
+ * Implementation of credential_manager_t.create_cdp_enumerator.
+ */
+static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
+ certificate_type_t type, identification_t *id)
+{
+ cdp_data_t *data = malloc_thing(cdp_data_t);
+ data->this = this;
+ data->type = type;
+ data->id = id;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_cdp, data,
+ (void*)destroy_cdp_data);
+}
+
+/**
+ * cleanup function for private data
+ */
+static void destroy_private_data(private_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for private keys
+ */
+static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
+{
+ return set->create_private_enumerator(set, data->type, data->keyid);
+}
+
+/**
+ * Implementation of credential_manager_t.create_private_enumerator.
+ */
+static enumerator_t* create_private_enumerator(
+ private_credential_manager_t *this,
+ key_type_t key, identification_t *keyid)
+{
+ private_data_t *data;
+
+ data = malloc_thing(private_data_t);
+ data->this = this;
+ data->type = key;
+ data->keyid = keyid;
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_private, data,
+ (void*)destroy_private_data);
+}
+
+/**
+ * Implementation of credential_manager_t.get_private_by_keyid.
+ */
+static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
+ key_type_t key, identification_t *keyid)
+{
+ private_key_t *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_private_enumerator(this, key, keyid);
+ if (enumerator->enumerate(enumerator, &found))
+ {
+ found->get_ref(found);
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * cleanup function for shared data
+ */
+static void destroy_shared_data(shared_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for shared keys
+ */
+static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
+{
+ return set->create_shared_enumerator(set, data->type, data->me, data->other);
+}
+
+/**
+ * Implementation of credential_manager_t.create_shared_enumerator.
+ */
+static enumerator_t *create_shared_enumerator(private_credential_manager_t *this,
+ shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ shared_data_t *data = malloc_thing(shared_data_t);
+ data->this = this;
+ data->type = type;
+ data->me = me;
+ data->other = other;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_shared, data,
+ (void*)destroy_shared_data);
+}
+
+/**
+ * Implementation of credential_manager_t.get_shared.
+ */
+static shared_key_t *get_shared(private_credential_manager_t *this,
+ shared_key_type_t type, identification_t *me,
+ identification_t *other)
+{
+ shared_key_t *current, *found = NULL;
+ id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
+ id_match_t *match_me, *match_other;
+ enumerator_t *enumerator;
+
+ enumerator = create_shared_enumerator(this, type, me, other);
+ while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
+ {
+ if (match_other > best_other ||
+ (match_other == best_other && match_me > best_me))
+ {
+ DESTROY_IF(found);
+ found = current->get_ref(current);
+ best_me = match_me;
+ best_other = match_other;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * add a credential set to the thread local list
+ */
+static void add_local_set(private_credential_manager_t *this,
+ credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = this->local_sets->get(this->local_sets);
+ if (!sets)
+ { /* first invocation */
+ sets = linked_list_create();
+ this->local_sets->set(this->local_sets, sets);
+ }
+ sets->insert_last(sets, set);
+}
+
+/**
+ * remove a credential set from the thread local list
+ */
+static void remove_local_set(private_credential_manager_t *this,
+ credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = this->local_sets->get(this->local_sets);
+ sets->remove(sets, set, NULL);
+}
+
+/**
+ * Implementation of credential_manager_t.cache_cert.
+ */
+static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
+{
+ credential_set_t *set;
+ enumerator_t *enumerator;
+
+ if (this->lock->try_write_lock(this->lock))
+ {
+ enumerator = this->sets->create_enumerator(this->sets);
+ while (enumerator->enumerate(enumerator, &set))
+ {
+ set->cache_cert(set, cert);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+ else
+ { /* we can't cache now as other threads are active, queue for later */
+ this->queue_mutex->lock(this->queue_mutex);
+ this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
+ this->queue_mutex->unlock(this->queue_mutex);
+ }
+}
+
+/**
+ * Try to cache certificates queued for caching
+ */
+static void cache_queue(private_credential_manager_t *this)
+{
+ credential_set_t *set;
+ certificate_t *cert;
+ enumerator_t *enumerator;
+
+ this->queue_mutex->lock(this->queue_mutex);
+ if (this->cache_queue->get_count(this->cache_queue) > 0 &&
+ this->lock->try_write_lock(this->lock))
+ {
+ while (this->cache_queue->remove_last(this->cache_queue,
+ (void**)&cert) == SUCCESS)
+ {
+ enumerator = this->sets->create_enumerator(this->sets);
+ while (enumerator->enumerate(enumerator, &set))
+ {
+ set->cache_cert(set, cert);
+ }
+ enumerator->destroy(enumerator);
+ cert->destroy(cert);
+ }
+ this->lock->unlock(this->lock);
+ }
+ this->queue_mutex->unlock(this->queue_mutex);
+}
+
+/**
+ * forward declaration
+ */
+static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
+ key_type_t type, identification_t *id, bool crl, bool ocsp);
+
+/**
+ * Do an OCSP request
+ */
+static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
+ certificate_t *subject, certificate_t *issuer)
+{
+ certificate_t *request, *response;
+ chunk_t send, receive;
+
+ /* TODO: requestor name, signature */
+ request = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
+ BUILD_CA_CERT, issuer,
+ BUILD_CERT, subject, BUILD_END);
+ if (!request)
+ {
+ DBG1(DBG_CFG, "generating ocsp request failed");
+ return NULL;
+ }
+
+ send = request->get_encoding(request);
+ request->destroy(request);
+
+ DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &receive,
+ FETCH_REQUEST_DATA, send,
+ FETCH_REQUEST_TYPE, "application/ocsp-request",
+ FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "ocsp request to %s failed", url);
+ chunk_free(&send);
+ return NULL;
+ }
+ chunk_free(&send);
+
+ response = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
+ BUILD_BLOB_ASN1_DER, receive, BUILD_END);
+ chunk_free(&receive);
+ if (!response)
+ {
+ DBG1(DBG_CFG, "parsing ocsp response failed");
+ return NULL;
+ }
+ return response;
+}
+
+/**
+ * check the signature of an OCSP response
+ */
+static bool verify_ocsp(private_credential_manager_t *this,
+ ocsp_response_t *response)
+{
+ certificate_t *issuer, *subject;
+ identification_t *responder;
+ ocsp_response_wrapper_t *wrapper;
+ enumerator_t *enumerator;
+ bool verified = FALSE;
+
+ wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
+ add_local_set(this, &wrapper->set);
+
+ subject = &response->certificate;
+ responder = subject->get_issuer(subject);
+ enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, &issuer, NULL))
+ {
+ if (this->cache->issued_by(this->cache, subject, issuer))
+ {
+ DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
+ issuer->get_subject(issuer));
+ verified = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ remove_local_set(this, &wrapper->set);
+ wrapper->destroy(wrapper);
+ return verified;
+}
+
+/**
+ * Get the better of two OCSP responses, and check for usable OCSP info
+ */
+static certificate_t *get_better_ocsp(private_credential_manager_t *this,
+ certificate_t *cand, certificate_t *best,
+ x509_t *subject, x509_t *issuer,
+ cert_validation_t *valid, bool cache)
+{
+ ocsp_response_t *response;
+ time_t revocation, this_update, next_update, valid_until;
+ crl_reason_t reason;
+ bool revoked = FALSE;
+
+ response = (ocsp_response_t*)cand;
+
+ /* check ocsp signature */
+ if (!verify_ocsp(this, response))
+ {
+ DBG1(DBG_CFG, "ocsp response verification failed");
+ cand->destroy(cand);
+ return best;
+ }
+ /* check if response contains our certificate */
+ switch (response->get_status(response, subject, issuer, &revocation, &reason,
+ &this_update, &next_update))
+ {
+ case VALIDATION_REVOKED:
+ /* subject has been revoked by a valid OCSP response */
+ DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
+ &revocation, TRUE, crl_reason_names, reason);
+ revoked = TRUE;
+ break;
+ case VALIDATION_GOOD:
+ /* results in either good or stale */
+ break;
+ default:
+ case VALIDATION_FAILED:
+ /* candidate unusable, does not contain our cert */
+ DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
+ cand->destroy(cand);
+ return best;
+ }
+
+ /* select the better of the two responses */
+ if (best == NULL || cand->is_newer(cand, best))
+ {
+ DESTROY_IF(best);
+ best = cand;
+ if (best->get_validity(best, NULL, NULL, &valid_until))
+ {
+ DBG1(DBG_CFG, " ocsp response is valid: until %T",
+ &valid_until, FALSE);
+ *valid = VALIDATION_GOOD;
+ if (cache)
+ { /* cache non-stale only, stale certs get refetched */
+ cache_cert(this, best);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, " ocsp response is stale: since %T",
+ &valid_until, FALSE);
+ *valid = VALIDATION_STALE;
+ }
+ }
+ else
+ {
+ *valid = VALIDATION_STALE;
+ cand->destroy(cand);
+ }
+ if (revoked)
+ { /* revoked always counts, even if stale */
+ *valid = VALIDATION_REVOKED;
+ }
+ return best;
+}
+
+/**
+ * validate a x509 certificate using OCSP
+ */
+static cert_validation_t check_ocsp(private_credential_manager_t *this,
+ x509_t *subject, x509_t *issuer,
+ auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ certificate_t *best = NULL, *current;
+ identification_t *keyid = NULL;
+ public_key_t *public;
+ chunk_t chunk;
+ char *uri = NULL;
+
+ /** lookup cache for valid OCSP responses */
+ enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
+ KEY_ANY, NULL, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ best = get_better_ocsp(this, current, best, subject, issuer,
+ &valid, FALSE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ DBG1(DBG_CFG, " using cached ocsp response");
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* derive the authorityKeyIdentifier from the issuer's public key */
+ current = &issuer->interface;
+ public = current->get_public_key(current);
+ if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+ }
+ /** fetch from configured OCSP responder URLs */
+ if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_ocsp(this, uri, &subject->interface,
+ &issuer->interface);
+ if (current)
+ {
+ best = get_better_ocsp(this, current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ DESTROY_IF(public);
+ DESTROY_IF(keyid);
+
+ /* fallback to URL fetching from subject certificate's URIs */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = subject->create_ocsp_uri_enumerator(subject);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_ocsp(this, uri, &subject->interface,
+ &issuer->interface);
+ if (current)
+ {
+ best = get_better_ocsp(this, current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri)
+ {
+ valid = VALIDATION_FAILED;
+ }
+ if (auth)
+ {
+ auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
+ if (valid == VALIDATION_GOOD)
+ { /* successful OCSP check fulfills also CRL constraint */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ }
+ }
+ DESTROY_IF(best);
+ return valid;
+}
+
+/**
+ * fetch a CRL from an URL
+ */
+static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
+{
+ certificate_t *crl;
+ chunk_t chunk;
+
+ DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "crl fetching failed");
+ return NULL;
+ }
+ crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
+ chunk_free(&chunk);
+ if (!crl)
+ {
+ DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
+ return NULL;
+ }
+ return crl;
+}
+
+/**
+ * check the signature of an CRL
+ */
+static bool verify_crl(private_credential_manager_t *this, certificate_t *crl)
+{
+ certificate_t *issuer;
+ enumerator_t *enumerator;
+ bool verified = FALSE;
+
+ enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl),
+ FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, &issuer, NULL))
+ {
+ if (this->cache->issued_by(this->cache, crl, issuer))
+ {
+ DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
+ issuer->get_subject(issuer));
+ verified = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return verified;
+}
+
+/**
+ * Get the better of two CRLs, and check for usable CRL info
+ */
+static certificate_t *get_better_crl(private_credential_manager_t *this,
+ certificate_t *cand, certificate_t *best,
+ x509_t *subject, x509_t *issuer,
+ cert_validation_t *valid, bool cache)
+{
+ enumerator_t *enumerator;
+ time_t revocation, valid_until;
+ crl_reason_t reason;
+ chunk_t serial;
+ crl_t *crl;
+
+ /* check CRL signature */
+ if (!verify_crl(this, cand))
+ {
+ DBG1(DBG_CFG, "crl response verification failed");
+ cand->destroy(cand);
+ return best;
+ }
+
+ crl = (crl_t*)cand;
+ enumerator = crl->create_enumerator(crl);
+ while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
+ {
+ if (chunk_equals(serial, subject->get_serial(subject)))
+ {
+ DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
+ &revocation, TRUE, crl_reason_names, reason);
+ *valid = VALIDATION_REVOKED;
+ enumerator->destroy(enumerator);
+ DESTROY_IF(best);
+ return cand;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* select the better of the two CRLs */
+ if (best == NULL || cand->is_newer(cand, best))
+ {
+ DESTROY_IF(best);
+ best = cand;
+ if (best->get_validity(best, NULL, NULL, &valid_until))
+ {
+ DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
+ *valid = VALIDATION_GOOD;
+ if (cache)
+ { /* we cache non-stale crls only, as a stale crls are refetched */
+ cache_cert(this, best);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
+ *valid = VALIDATION_STALE;
+ }
+ }
+ else
+ {
+ *valid = VALIDATION_STALE;
+ cand->destroy(cand);
+ }
+ return best;
+}
+
+/**
+ * validate a x509 certificate using CRL
+ */
+static cert_validation_t check_crl(private_credential_manager_t *this,
+ x509_t *subject, x509_t *issuer,
+ auth_cfg_t *auth)
+{
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ identification_t *keyid = NULL;
+ certificate_t *best = NULL;
+ certificate_t *current;
+ public_key_t *public;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+ char *uri = NULL;
+
+ /* derive the authorityKeyIdentifier from the issuer's public key */
+ current = &issuer->interface;
+ public = current->get_public_key(current);
+ if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+
+ /* find a cached crl by authorityKeyIdentifier */
+ enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY,
+ keyid, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ best = get_better_crl(this, current, best, subject, issuer,
+ &valid, FALSE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ DBG1(DBG_CFG, " using cached crl");
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* fallback to fetching crls from credential sets cdps */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid);
+
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_crl(this, uri);
+ if (current)
+ {
+ best = get_better_crl(this, current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ keyid->destroy(keyid);
+ }
+ DESTROY_IF(public);
+
+ /* fallback to fetching crls from cdps from subject's certificate */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = subject->create_crl_uri_enumerator(subject);
+
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_crl(this, uri);
+ if (current)
+ {
+ best = get_better_crl(this, current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri)
+ {
+ valid = VALIDATION_FAILED;
+ }
+ if (auth)
+ {
+ if (valid == VALIDATION_SKIPPED)
+ { /* if we skipped CRL validation, we use the result of OCSP for
+ * constraint checking */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION,
+ auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
+ }
+ else
+ {
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
+ }
+ }
+ DESTROY_IF(best);
+ return valid;
+}
+
+/**
+ * check a certificate for optional IP address block constraints
+ */
+static bool check_ip_addr_block_constraints(x509_t *subject, x509_t *issuer)
+{
+ bool subject_constraint = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS;
+ bool issuer_constraint = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS;
+ bool contained = TRUE;
+
+ enumerator_t *subject_enumerator, *issuer_enumerator;
+ traffic_selector_t *subject_ts, *issuer_ts;
+
+ if (!subject_constraint && !issuer_constraint)
+ {
+ return TRUE;
+ }
+ if (!subject_constraint)
+ {
+ DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
+ return FALSE;
+ }
+ if (!issuer_constraint)
+ {
+ DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension");
+ return FALSE;
+ }
+ subject_enumerator = subject->create_ipAddrBlock_enumerator(subject);
+ while (subject_enumerator->enumerate(subject_enumerator, &subject_ts))
+ {
+ contained = FALSE;
+
+ issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer);
+ while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts))
+ {
+ if (subject_ts->is_contained_in(subject_ts, issuer_ts))
+ {
+ DBG2(DBG_CFG, " subject address block %R is contained in "
+ "issuer address block %R", subject_ts, issuer_ts);
+ contained = TRUE;
+ break;
+ }
+ }
+ issuer_enumerator->destroy(issuer_enumerator);
+ if (!contained)
+ {
+ DBG1(DBG_CFG, "subject address block %R is not contained in any "
+ "issuer address block", subject_ts);
+ break;
+ }
+ }
+ subject_enumerator->destroy(subject_enumerator);
+ return contained;
+}
+
+/**
+ * check a certificate for its lifetime
+ */
+static bool check_certificate(private_credential_manager_t *this,
+ certificate_t *subject, certificate_t *issuer,
+ bool crl, bool ocsp, auth_cfg_t *auth)
+{
+ time_t not_before, not_after;
+
+ if (!subject->get_validity(subject, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ if (issuer->get_type(issuer) == CERT_X509 &&
+ subject->get_type(subject) == CERT_X509)
+ {
+ if (!check_ip_addr_block_constraints((x509_t*)subject, (x509_t*)issuer))
+ {
+ return FALSE;
+ }
+ if (ocsp || crl)
+ {
+ DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
+ subject->get_subject(subject));
+ }
+ if (ocsp)
+ {
+ switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
+ {
+ case VALIDATION_GOOD:
+ DBG1(DBG_CFG, "certificate status is good");
+ return TRUE;
+ case VALIDATION_REVOKED:
+ /* has already been logged */
+ return FALSE;
+ case VALIDATION_SKIPPED:
+ DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
+ break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
+ break;
+ case VALIDATION_FAILED:
+ DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
+ break;
+ }
+ }
+ if (crl)
+ {
+ switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
+ {
+ case VALIDATION_GOOD:
+ DBG1(DBG_CFG, "certificate status is good");
+ return TRUE;
+ case VALIDATION_REVOKED:
+ /* has already been logged */
+ return FALSE;
+ case VALIDATION_FAILED:
+ case VALIDATION_SKIPPED:
+ DBG1(DBG_CFG, "certificate status is not available");
+ break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
+ break;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Get a trusted certificate from a credential set
+ */
+static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
+ key_type_t type, identification_t *id)
+{
+ certificate_t *subject;
+ public_key_t *public;
+
+ subject = get_cert(this, CERT_ANY, type, id, TRUE);
+ if (!subject)
+ {
+ return NULL;
+ }
+ public = subject->get_public_key(subject);
+ if (!public)
+ {
+ subject->destroy(subject);
+ return NULL;
+ }
+ public->destroy(public);
+ return subject;
+}
+
+/**
+ * Get the issuing certificate of a subject certificate
+ */
+static certificate_t *get_issuer_cert(private_credential_manager_t *this,
+ certificate_t *subject, bool trusted)
+{
+ enumerator_t *enumerator;
+ certificate_t *issuer = NULL, *candidate;
+
+ enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
+ subject->get_issuer(subject), trusted);
+ while (enumerator->enumerate(enumerator, &candidate))
+ {
+ if (this->cache->issued_by(this->cache, subject, candidate))
+ {
+ issuer = candidate->get_ref(candidate);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return issuer;
+}
+
+/**
+ * try to verify the trust chain of subject, return TRUE if trusted
+ */
+static bool verify_trust_chain(private_credential_manager_t *this,
+ certificate_t *subject, auth_cfg_t *result,
+ bool trusted, bool crl, bool ocsp)
+{
+ certificate_t *current, *issuer;
+ x509_t *x509;
+ auth_cfg_t *auth;
+ int pathlen, pathlen_constraint;
+
+ auth = auth_cfg_create();
+ current = subject->get_ref(subject);
+
+ for (pathlen = 0; pathlen <= X509_MAX_PATH_LEN; pathlen++)
+ {
+ issuer = get_issuer_cert(this, current, TRUE);
+ if (issuer)
+ {
+ /* accept only self-signed CAs as trust anchor */
+ if (this->cache->issued_by(this->cache, issuer, issuer))
+ {
+ auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
+ issuer->get_subject(issuer));
+ trusted = TRUE;
+ }
+ else
+ {
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using trusted intermediate ca certificate "
+ "\"%Y\"", issuer->get_subject(issuer));
+ }
+ }
+ else
+ {
+ issuer = get_issuer_cert(this, current, FALSE);
+ if (issuer)
+ {
+ if (current->equals(current, issuer))
+ {
+ DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
+ current->get_subject(current));
+ issuer->destroy(issuer);
+ break;
+ }
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using untrusted intermediate certificate "
+ "\"%Y\"", issuer->get_subject(issuer));
+ }
+ else
+ {
+ DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
+ current->get_subject(current));
+ break;
+ }
+ }
+ if (!check_certificate(this, current, issuer, crl, ocsp,
+ current == subject ? auth : NULL))
+ {
+ trusted = FALSE;
+ issuer->destroy(issuer);
+ break;
+ }
+
+ /* check path length constraint */
+ x509 = (x509_t*)issuer;
+ pathlen_constraint = x509->get_pathLenConstraint(x509);
+ if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
+ pathlen > pathlen_constraint)
+ {
+ DBG1(DBG_CFG, "path length of %d violates constraint of %d",
+ pathlen, pathlen_constraint);
+ trusted = FALSE;
+ issuer->destroy(issuer);
+ break;
+ }
+ current->destroy(current);
+ current = issuer;
+ if (trusted)
+ {
+ DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
+ pathlen);
+ break;
+ }
+ }
+ current->destroy(current);
+ if (pathlen > X509_MAX_PATH_LEN)
+ {
+ DBG1(DBG_CFG, "maximum path length of %d exceeded", X509_MAX_PATH_LEN);
+ }
+ if (trusted)
+ {
+ result->merge(result, auth, FALSE);
+ }
+ auth->destroy(auth);
+ return trusted;
+}
+
+/**
+ * enumerator for trusted certificates
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** enumerator over candidate peer certificates */
+ enumerator_t *candidates;
+ /** reference to the credential_manager */
+ private_credential_manager_t *this;
+ /** type of the requested key */
+ key_type_t type;
+ /** identity the requested key belongs to */
+ identification_t *id;
+ /** TRUE to do CRL checking */
+ bool crl;
+ /** TRUE to do OCSP checking */
+ bool ocsp;
+ /** pretrusted certificate we have served at first invocation */
+ certificate_t *pretrusted;
+ /** currently enumerating auth config */
+ auth_cfg_t *auth;
+} trusted_enumerator_t;
+
+/**
+ * Implements trusted_enumerator_t.enumerate
+ */
+static bool trusted_enumerate(trusted_enumerator_t *this,
+ certificate_t **cert, auth_cfg_t **auth)
+{
+ certificate_t *current;
+
+ DESTROY_IF(this->auth);
+ this->auth = auth_cfg_create();
+
+ if (!this->candidates)
+ {
+ /* first invocation, build enumerator for next one */
+ this->candidates = create_cert_enumerator(this->this, CERT_ANY,
+ this->type, this->id, FALSE);
+ /* check if we have a trusted certificate for that peer */
+ this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
+ if (this->pretrusted)
+ {
+ /* if we find a trusted self signed certificate, we just accept it.
+ * However, in order to fulfill authorization rules, we try to build
+ * the trust chain if it is not self signed */
+ if (this->this->cache->issued_by(this->this->cache,
+ this->pretrusted, this->pretrusted) ||
+ verify_trust_chain(this->this, this->pretrusted, this->auth,
+ TRUE, this->crl, this->ocsp))
+ {
+ this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
+ this->pretrusted->get_ref(this->pretrusted));
+ DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
+ this->pretrusted->get_subject(this->pretrusted));
+ *cert = this->pretrusted;
+ if (auth)
+ {
+ *auth = this->auth;
+ }
+ return TRUE;
+ }
+ }
+ }
+ /* try to verify the trust chain for each certificate found */
+ while (this->candidates->enumerate(this->candidates, &current))
+ {
+ if (this->pretrusted &&
+ this->pretrusted->equals(this->pretrusted, current))
+ { /* skip pretrusted certificate we already served */
+ continue;
+ }
+
+ DBG1(DBG_CFG, " using certificate \"%Y\"",
+ current->get_subject(current));
+ if (verify_trust_chain(this->this, current, this->auth, FALSE,
+ this->crl, this->ocsp))
+ {
+ *cert = current;
+ if (auth)
+ {
+ *auth = this->auth;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Implements trusted_enumerator_t.destroy
+ */
+static void trusted_destroy(trusted_enumerator_t *this)
+{
+ DESTROY_IF(this->pretrusted);
+ DESTROY_IF(this->auth);
+ DESTROY_IF(this->candidates);
+ free(this);
+}
+
+/**
+ * create an enumerator over trusted certificates and their trustchain
+ */
+static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
+ key_type_t type, identification_t *id, bool crl, bool ocsp)
+{
+ trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
+
+ enumerator->public.enumerate = (void*)trusted_enumerate;
+ enumerator->public.destroy = (void*)trusted_destroy;
+
+ enumerator->candidates = NULL;
+ enumerator->this = this;
+ enumerator->type = type;
+ enumerator->id = id;
+ enumerator->crl = crl;
+ enumerator->ocsp = ocsp;
+ enumerator->pretrusted = NULL;
+ enumerator->auth = NULL;
+
+ return &enumerator->public;
+}
+
+/**
+ * enumerator for public keys
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** enumerator over candidate peer certificates */
+ enumerator_t *inner;
+ /** reference to the credential_manager */
+ private_credential_manager_t *this;
+ /** currently enumerating key */
+ public_key_t *current;
+ /** credset wrapper around auth config */
+ auth_cfg_wrapper_t *wrapper;
+} public_enumerator_t;
+
+/**
+ * Implements public_enumerator_t.enumerate
+ */
+static bool public_enumerate(public_enumerator_t *this,
+ public_key_t **key, auth_cfg_t **auth)
+{
+ certificate_t *cert;
+
+ while (this->inner->enumerate(this->inner, &cert, auth))
+ {
+ DESTROY_IF(this->current);
+ this->current = cert->get_public_key(cert);
+ if (this->current)
+ {
+ *key = this->current;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Implements public_enumerator_t.destroy
+ */
+static void public_destroy(public_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ if (this->wrapper)
+ {
+ remove_local_set(this->this, &this->wrapper->set);
+ this->wrapper->destroy(this->wrapper);
+ }
+ this->this->lock->unlock(this->this->lock);
+
+ /* check for delayed certificate cache queue */
+ cache_queue(this->this);
+ free(this);
+}
+
+/**
+ * Implementation of credential_manager_t.create_public_enumerator.
+ */
+static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
+ key_type_t type, identification_t *id, auth_cfg_t *auth)
+{
+ public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
+
+ enumerator->public.enumerate = (void*)public_enumerate;
+ enumerator->public.destroy = (void*)public_destroy;
+ enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE);
+ enumerator->this = this;
+ enumerator->current = NULL;
+ enumerator->wrapper = NULL;
+ if (auth)
+ {
+ enumerator->wrapper = auth_cfg_wrapper_create(auth);
+ add_local_set(this, &enumerator->wrapper->set);
+ }
+ this->lock->read_lock(this->lock);
+ return &enumerator->public;
+}
+
+/**
+ * Check if a certificate's keyid is contained in the auth helper
+ */
+static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
+{
+ enumerator_t *enumerator;
+ identification_t *value;
+ auth_rule_t type;
+ bool found = FALSE;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ if (type == AUTH_RULE_CA_CERT &&
+ cert->equals(cert, (certificate_t*)value))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * build a trustchain from subject up to a trust anchor in trusted
+ */
+static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
+ certificate_t *subject, auth_cfg_t *auth)
+{
+ certificate_t *issuer, *current;
+ auth_cfg_t *trustchain;
+ int pathlen = 0;
+
+ trustchain = auth_cfg_create();
+
+ current = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (!current)
+ {
+ /* no trust anchor specified, return this cert only */
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
+ subject->get_ref(subject));
+ return trustchain;
+ }
+ current = subject->get_ref(subject);
+ while (TRUE)
+ {
+ if (auth_contains_cacert(auth, current))
+ {
+ trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
+ return trustchain;
+ }
+ if (subject == current)
+ {
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
+ }
+ else
+ {
+ trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
+ }
+ issuer = get_issuer_cert(this, current, FALSE);
+ if (!issuer || issuer->equals(issuer, current) ||
+ pathlen > X509_MAX_PATH_LEN)
+ {
+ DESTROY_IF(issuer);
+ break;
+ }
+ current = issuer;
+ pathlen++;
+ }
+ trustchain->destroy(trustchain);
+ return NULL;
+}
+
+/**
+ * find a private key of a give certificate
+ */
+static private_key_t *get_private_by_cert(private_credential_manager_t *this,
+ certificate_t *cert, key_type_t type)
+{
+ private_key_t *private = NULL;
+ identification_t *keyid;
+ chunk_t chunk;
+ public_key_t *public;
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+ private = get_private_by_keyid(this, type, keyid);
+ keyid->destroy(keyid);
+ }
+ public->destroy(public);
+ }
+ return private;
+}
+
+/**
+ * Implementation of credential_manager_t.get_private.
+ */
+static private_key_t *get_private(private_credential_manager_t *this,
+ key_type_t type, identification_t *id,
+ auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ private_key_t *private = NULL;
+ auth_cfg_t *trustchain;
+
+ /* check if this is a lookup by key ID, and do it if so */
+ if (id && id->get_type(id) == ID_KEY_ID)
+ {
+ private = get_private_by_keyid(this, type, id);
+ if (private)
+ {
+ return private;
+ }
+ }
+
+ /* if a specific certificate is preferred, check for a matching key */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ }
+ return private;
+ }
+ }
+
+ /* try to build a trust chain for each certificate found */
+ enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ break;
+ }
+ private->destroy(private);
+ private = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* if no valid trustchain was found, fall back to the first usable cert */
+ if (!private)
+ {
+ enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return private;
+}
+
+/**
+ * Implementation of credential_manager_t.flush_cache.
+ */
+static void flush_cache(private_credential_manager_t *this,
+ certificate_type_t type)
+{
+ this->cache->flush(this->cache, type);
+}
+
+/**
+ * Implementation of credential_manager_t.add_set.
+ */
+static void add_set(private_credential_manager_t *this,
+ credential_set_t *set)
+{
+ this->lock->write_lock(this->lock);
+ this->sets->insert_last(this->sets, set);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of credential_manager_t.remove_set.
+ */
+static void remove_set(private_credential_manager_t *this, credential_set_t *set)
+{
+ this->lock->write_lock(this->lock);
+ this->sets->remove(this->sets, set, NULL);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of credential_manager_t.destroy
+ */
+static void destroy(private_credential_manager_t *this)
+{
+ cache_queue(this);
+ this->cache_queue->destroy(this->cache_queue);
+ this->sets->remove(this->sets, this->cache, NULL);
+ this->sets->destroy(this->sets);
+ this->local_sets->destroy(this->local_sets);
+ this->cache->destroy(this->cache);
+ this->lock->destroy(this->lock);
+ this->queue_mutex->destroy(this->queue_mutex);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+credential_manager_t *credential_manager_create()
+{
+ private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
+
+ this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator;
+ this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator;
+ this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator;
+ this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
+ this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
+ this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private;
+ this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator;
+ this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
+ this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert;
+ this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
+ this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
+ this->public.destroy = (void(*)(credential_manager_t*))destroy;
+
+ this->sets = linked_list_create();
+ this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
+ this->cache = cert_cache_create();
+ this->cache_queue = linked_list_create();
+ this->sets->insert_first(this->sets, this->cache);
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ this->queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/credentials/credential_manager.h b/src/libcharon/credentials/credential_manager.h
new file mode 100644
index 000000000..0448da992
--- /dev/null
+++ b/src/libcharon/credentials/credential_manager.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2007-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 credential_manager credential_manager
+ * @{ @ingroup ccredentials
+ */
+
+#ifndef CREDENTIAL_MANAGER_H_
+#define CREDENTIAL_MANAGER_H_
+
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+#include <config/auth_cfg.h>
+#include <credentials/credential_set.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/shared_key.h>
+#include <credentials/certificates/certificate.h>
+
+typedef struct credential_manager_t credential_manager_t;
+
+/**
+ * Manages credentials using credential_sets.
+ *
+ * The credential manager is the entry point of the credential framework. It
+ * uses so called "sets" to access credentials in a modular fashion, these
+ * are implemented through the credential_set_t interface.
+ * The manager additionally does trust chain verification and trust status
+ * chaching. A set may call the managers methods if it needs credentials itself,
+ * the manager uses recursive locking.
+ *
+ * @verbatim
+
+ +-------+ +----------------+
+ | A | | | +------------------+
+ | u | -----> | | ------> | +------------------+
+ | t | | credential- | | | +------------------+
+ | h | -----> | manager | ------> +--| | credential- | => IPC
+ | e | | | +--| sets |
+ | n | +--> | | ------> +------------------+
+ | t | | | | |
+ | i | | | | |
+ | c | | +----------------+ |
+ | a | | |
+ | t | +----------------------------------------------+
+ | o | may be recursive
+ | r |
+ +-------+
+
+ @endverbatim
+ *
+ * The credential manager uses rwlocks for performance reasons, credential
+ * sets must be fully thread save.
+ */
+struct credential_manager_t {
+
+ /**
+ * Create an enumerator over all certificates.
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id subject this certificate belongs to
+ * @param trusted TRUE to list trusted certificates only
+ * @return enumerator over the certificates
+ */
+ enumerator_t *(*create_cert_enumerator)(credential_manager_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Create an enumerator over all shared keys.
+ *
+ * The enumerator enumerates over:
+ * shared_key_t*, id_match_t me, id_match_t other
+ * But must accepts values for the id_matches.
+ *
+ * @param type kind of requested shared key
+ * @param first first subject between key is shared
+ * @param second second subject between key is shared
+ * @return enumerator over shared keys
+ */
+ enumerator_t *(*create_shared_enumerator)(credential_manager_t *this,
+ shared_key_type_t type,
+ identification_t *first, identification_t *second);
+ /**
+ * Create an enumerator over all Certificate Distribution Points.
+ *
+ * @param type kind of certificate the point distributes
+ * @param id identification of the distributed certificate
+ * @return enumerator of CDPs as char*
+ */
+ enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this,
+ certificate_type_t type, identification_t *id);
+ /**
+ * Get a trusted or untrusted certificate.
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id subject this certificate belongs to
+ * @param trusted TRUE to get a trusted certificate only
+ * @return certificate, if found, NULL otherwise
+ */
+ certificate_t *(*get_cert)(credential_manager_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Get the best matching shared key for two IDs.
+ *
+ * @param type kind of requested shared key
+ * @param me own identity
+ * @param other peers identity
+ * @return shared_key_t, NULL if none found
+ */
+ shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other);
+ /**
+ * Get a private key to create a signature.
+ *
+ * The get_private() method gets a secret private key identified by either
+ * the keyid itself or an id the key belongs to.
+ * The auth parameter contains additional information, such as receipients
+ * trusted CA certs. Auth gets filled with subject and CA certificates
+ * needed to validate a created signature.
+ *
+ * @param type type of the key to get
+ * @param id identification the key belongs to
+ * @param auth auth config, including trusted CA certificates
+ * @return private_key_t, NULL if none found
+ */
+ private_key_t* (*get_private)(credential_manager_t *this, key_type_t type,
+ identification_t *id, auth_cfg_t *auth);
+
+ /**
+ * Create an enumerator over trusted public keys.
+ *
+ * This method gets a an enumerator over trusted public keys to verify a
+ * signature created by id. The auth parameter contains additional
+ * authentication infos, e.g. peer and intermediate certificates.
+ * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *,
+ * where the auth config helper contains rules for constraint checks.
+ *
+ * @param type type of the key to get
+ * @param id owner of the key, signer of the signature
+ * @param auth authentication infos
+ * @return enumerator
+ */
+ enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
+ key_type_t type, identification_t *id, auth_cfg_t *auth);
+
+ /**
+ * Cache a certificate by invoking cache_cert() on all registerd sets.
+ *
+ * @param cert certificate to cache
+ */
+ void (*cache_cert)(credential_manager_t *this, certificate_t *cert);
+
+ /**
+ * Flush the certificate cache.
+ *
+ * Only the managers local cache is flushed, but not the sets cache filled
+ * by the cache_cert() method.
+ *
+ * @param type type of certificate to flush, or CERT_ANY
+ */
+ void (*flush_cache)(credential_manager_t *this, certificate_type_t type);
+
+ /**
+ * Register a credential set to the manager.
+ *
+ * @param set set to register
+ */
+ void (*add_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Unregister a credential set from the manager.
+ *
+ * @param set set to unregister
+ */
+ void (*remove_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Destroy a credential_manager instance.
+ */
+ void (*destroy)(credential_manager_t *this);
+};
+
+/**
+ * Create a credential_manager instance.
+ */
+credential_manager_t *credential_manager_create();
+
+#endif /** CREDENTIAL_MANAGER_H_ @}*/
diff --git a/src/libcharon/credentials/credential_set.h b/src/libcharon/credentials/credential_set.h
new file mode 100644
index 000000000..274eb3feb
--- /dev/null
+++ b/src/libcharon/credentials/credential_set.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup credential_set credential_set
+ * @{ @ingroup ccredentials
+ */
+
+#ifndef CREDENTIAL_SET_H_
+#define CREDENTIAL_SET_H_
+
+#include <credentials/keys/public_key.h>
+#include <credentials/keys/shared_key.h>
+#include <credentials/certificates/certificate.h>
+
+typedef struct credential_set_t credential_set_t;
+
+/**
+ * A set of credentials.
+ *
+ * Contains private keys, shared keys and different kinds of certificates.
+ * Enumerators are used because queries might return multiple matches.
+ * Filter parameters restrict enumeration over specific items only.
+ * See credential_manager_t for an overview of the credential framework.
+ *
+ * A credential set enumerator may not block the credential set, i.e. multiple
+ * threads must be able to hold multiple enumerators, as the credential manager
+ * is higly parallelized. The best way to achieve this is by using shared
+ * read locks for the enumerators only. Otherwiese deadlocks will occur.
+ * The writing cache_cert() routine is called by the manager only if no
+ * enumerator is alive, so it is save to use a write lock there.
+ */
+struct credential_set_t {
+
+ /**
+ * Create an enumerator over private keys (private_key_t).
+ *
+ * The id is either a key identifier of the requested key, or an identity
+ * of the key owner.
+ *
+ * @param type type of requested private key
+ * @param id key identifier/owner
+ * @return enumerator over private_key_t's.
+ */
+ enumerator_t *(*create_private_enumerator)(credential_set_t *this,
+ key_type_t type, identification_t *id);
+ /**
+ * Create an enumerator over certificates (certificate_t).
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id identity (subject) this certificate belongs to
+ * @param trusted whether the certificate must be trustworthy
+ * @return enumerator as described above
+ */
+ enumerator_t *(*create_cert_enumerator)(credential_set_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Create an enumerator over shared keys (shared_key_t).
+ *
+ * The enumerator enumerates over:
+ * shared_key_t*, id_match_t me, id_match_t other
+ * But must accept NULL values for the id_matches.
+ *
+ * @param type kind of requested shared key
+ * @param me own identity
+ * @param other other identity who owns that secret
+ * @return enumerator as described above
+ */
+ enumerator_t *(*create_shared_enumerator)(credential_set_t *this,
+ shared_key_type_t type,
+ identification_t *me, identification_t *other);
+
+ /**
+ * Create an enumerator over certificate distribution points.
+ *
+ * @param type type of the certificate to get a CDP
+ * @param id identification of the distributed certificate
+ * @return an enumerator over CDPs as char*
+ */
+ enumerator_t *(*create_cdp_enumerator)(credential_set_t *this,
+ certificate_type_t type, identification_t *id);
+
+ /**
+ * Cache a certificate in the credential set.
+ *
+ * The caching policy is implementation dependent, the sets may cache the
+ * certificate in-memory, persistent on disk or not at all.
+ *
+ * @param cert certificate to cache
+ */
+ void (*cache_cert)(credential_set_t *this, certificate_t *cert);
+};
+
+#endif /** CREDENTIAL_SET_H_ @}*/
diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.c b/src/libcharon/credentials/sets/auth_cfg_wrapper.c
new file mode 100644
index 000000000..82e33d283
--- /dev/null
+++ b/src/libcharon/credentials/sets/auth_cfg_wrapper.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2008-2009 Martin Willi
+ * 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 <daemon.h>
+
+#include "auth_cfg_wrapper.h"
+
+typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
+
+/**
+ * private data of auth_cfg_wrapper
+ */
+struct private_auth_cfg_wrapper_t {
+
+ /**
+ * public functions
+ */
+ auth_cfg_wrapper_t public;
+
+ /**
+ * wrapped auth info
+ */
+ auth_cfg_t *auth;
+};
+
+/**
+ * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner enumerator from auth_cfg */
+ enumerator_t *inner;
+ /** wrapped auth round */
+ auth_cfg_t *auth;
+ /** enumerated cert type */
+ certificate_type_t cert;
+ /** enumerated key type */
+ key_type_t key;
+ /** enumerated id */
+ identification_t *id;
+} wrapper_enumerator_t;
+
+/**
+ * Tries to fetch a certificate that was supplied as "Hash and URL"
+ * (replaces rule type and value in place).
+ */
+static bool fetch_cert(wrapper_enumerator_t *enumerator,
+ auth_rule_t *rule, void **value)
+{
+ char *url = (char*)*value;
+ if (!url)
+ {
+ /* fetching the certificate previously failed */
+ return FALSE;
+ }
+
+ chunk_t data;
+ certificate_t *cert;
+
+ DBG1(DBG_CFG, " fetching certificate from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, " fetching certificate failed");
+ /* we set the item to NULL, so we can skip it */
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, NULL);
+ return FALSE;
+ }
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, data, BUILD_END);
+ free(data.ptr);
+
+ if (!cert)
+ {
+ DBG1(DBG_CFG, " parsing fetched certificate failed");
+ /* we set the item to NULL, so we can skip it */
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, NULL);
+ return FALSE;
+ }
+
+ DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert));
+ charon->credentials->cache_cert(charon->credentials, cert);
+
+ if (*rule == AUTH_HELPER_IM_HASH_URL)
+ {
+ *rule = AUTH_HELPER_IM_CERT;
+ }
+ else
+ {
+ *rule = AUTH_HELPER_SUBJECT_CERT;
+ }
+ *value = cert;
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, cert->get_ref(cert));
+ return TRUE;
+}
+
+/**
+ * enumerate function for wrapper_enumerator_t
+ */
+static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
+{
+ auth_rule_t rule;
+ certificate_t *current;
+ public_key_t *public;
+
+ while (this->inner->enumerate(this->inner, &rule, &current))
+ {
+ if (rule == AUTH_HELPER_IM_HASH_URL ||
+ rule == AUTH_HELPER_SUBJECT_HASH_URL)
+ { /* on-demand fetching of hash and url certificates */
+ if (!fetch_cert(this, &rule, (void**)&current))
+ {
+ continue;
+ }
+ }
+ else if (rule != AUTH_HELPER_SUBJECT_CERT &&
+ rule != AUTH_HELPER_IM_CERT)
+ { /* handle only HELPER certificates */
+ continue;
+ }
+ if (this->cert != CERT_ANY && this->cert != current->get_type(current))
+ { /* CERT type requested, but does not match */
+ continue;
+ }
+ public = current->get_public_key(current);
+ if (this->key != KEY_ANY && !public)
+ { /* key type requested, but no public key */
+ DESTROY_IF(public);
+ continue;
+ }
+ if (this->key != KEY_ANY && public && this->key != public->get_type(public))
+ { /* key type requested, but public key has another type */
+ DESTROY_IF(public);
+ continue;
+ }
+ DESTROY_IF(public);
+ if (this->id && !current->has_subject(current, this->id))
+ { /* subject requested, but does not match */
+ continue;
+ }
+ *cert = current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for wrapper_enumerator_t
+ */
+static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ wrapper_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+ enumerator = malloc_thing(wrapper_enumerator_t);
+ enumerator->auth = this->auth;
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->inner = this->auth->create_enumerator(this->auth);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of auth_cfg_wrapper_t.destroy
+ */
+static void destroy(private_auth_cfg_wrapper_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
+{
+ private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_wrapper_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy;
+
+ this->auth = auth;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.h b/src/libcharon/credentials/sets/auth_cfg_wrapper.h
new file mode 100644
index 000000000..7653fcdbf
--- /dev/null
+++ b/src/libcharon/credentials/sets/auth_cfg_wrapper.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008-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 auth_cfg_wrapper auth_cfg_wrapper
+ * @{ @ingroup sets
+ */
+
+#ifndef AUTH_CFG_WRAPPER_H_
+#define AUTH_CFG_WRAPPER_H_
+
+#include <config/auth_cfg.h>
+#include <credentials/credential_set.h>
+
+typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
+
+/**
+ * A wrapper around auth_cfg_t to handle it as a credential set.
+ */
+struct auth_cfg_wrapper_t {
+
+ /**
+ * implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy a auth_cfg_wrapper instance.
+ */
+ void (*destroy)(auth_cfg_wrapper_t *this);
+};
+
+/**
+ * Create a auth_cfg_wrapper instance.
+ *
+ * @param auth the wrapped auth info
+ * @return wrapper around auth
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
+
+#endif /** AUTH_CFG_WRAPPER_H_ @}*/
diff --git a/src/libcharon/credentials/sets/cert_cache.c b/src/libcharon/credentials/sets/cert_cache.c
new file mode 100644
index 000000000..176accce2
--- /dev/null
+++ b/src/libcharon/credentials/sets/cert_cache.c
@@ -0,0 +1,390 @@
+/*
+ * 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.
+ */
+
+#include "cert_cache.h"
+
+#include <time.h>
+#include <sched.h>
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+/** cache size, a power of 2 for fast modulo */
+#define CACHE_SIZE 32
+
+/** attempts to acquire a cache lock */
+#define REPLACE_TRIES 5
+
+typedef struct private_cert_cache_t private_cert_cache_t;
+typedef struct relation_t relation_t;
+
+/**
+ * A trusted relation between subject and issuer
+ */
+struct relation_t {
+
+ /**
+ * subject of this relation
+ */
+ certificate_t *subject;
+
+ /**
+ * issuer of this relation
+ */
+ certificate_t *issuer;
+
+ /**
+ * Cache hits
+ */
+ u_int hits;
+
+ /**
+ * Lock for this relation
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * private data of cert_cache
+ */
+struct private_cert_cache_t {
+
+ /**
+ * public functions
+ */
+ cert_cache_t public;
+
+ /**
+ * array of trusted subject-issuer relations
+ */
+ relation_t relations[CACHE_SIZE];
+};
+
+/**
+ * Cache relation in a free slot/replace an other
+ */
+static void cache(private_cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer)
+{
+ relation_t *rel;
+ int i, offset, try;
+ u_int total_hits = 0;
+
+ /* check for a unused relation slot first */
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+
+ if (!rel->subject && rel->lock->try_write_lock(rel->lock))
+ {
+ /* double-check having lock */
+ if (!rel->subject)
+ {
+ rel->subject = subject->get_ref(subject);
+ rel->issuer = issuer->get_ref(issuer);
+ return rel->lock->unlock(rel->lock);
+ }
+ rel->lock->unlock(rel->lock);
+ }
+ total_hits += rel->hits;
+ }
+ /* run several attempts to replace a random slot, never block. */
+ for (try = 0; try < REPLACE_TRIES; try++)
+ {
+ /* replace a random relation */
+ offset = random();
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[(i + offset) % CACHE_SIZE];
+
+ if (rel->hits > total_hits / CACHE_SIZE)
+ { /* skip often used slots */
+ continue;
+ }
+ if (rel->lock->try_write_lock(rel->lock))
+ {
+ if (rel->subject)
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ }
+ rel->subject = subject->get_ref(subject);
+ rel->issuer = issuer->get_ref(issuer);
+ rel->hits = 0;
+ return rel->lock->unlock(rel->lock);
+ }
+ }
+ /* give other threads a chance to release locks */
+ sched_yield();
+ }
+}
+
+/**
+ * Implementation of cert_cache_t.issued_by.
+ */
+static bool issued_by(private_cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer)
+{
+ relation_t *found = NULL, *current;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ current = &this->relations[i];
+
+ current->lock->read_lock(current->lock);
+ if (current->subject)
+ {
+ /* check for equal issuer */
+ if (issuer->equals(issuer, current->issuer))
+ {
+ /* reuse issuer instance in cache() */
+ issuer = current->issuer;
+ if (subject->equals(subject, current->subject))
+ {
+ /* write hit counter is not locked, but not critical */
+ current->hits++;
+ found = current;
+ }
+ }
+ }
+ current->lock->unlock(current->lock);
+ if (found)
+ {
+ return TRUE;
+ }
+ }
+ /* no cache hit, check and cache signature */
+ if (subject->issued_by(subject, issuer))
+ {
+ cache(this, subject, issuer);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * certificate enumerator implemenation
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** type of requested certificate */
+ certificate_type_t cert;
+ /** type of requested key */
+ key_type_t key;
+ /** ID to get a cert for */
+ identification_t *id;
+ /** cache */
+ relation_t *relations;
+ /** current position in array cache */
+ int index;
+ /** currently locked relation */
+ int locked;
+} cert_enumerator_t;
+
+/**
+ * filter function for certs enumerator
+ */
+static bool cert_enumerate(cert_enumerator_t *this, certificate_t **out)
+{
+ public_key_t *public;
+ relation_t *rel;
+
+ if (this->locked >= 0)
+ {
+ rel = &this->relations[this->locked];
+ rel->lock->unlock(rel->lock);
+ this->locked = -1;
+ }
+
+ while (++this->index < CACHE_SIZE)
+ {
+ rel = &this->relations[this->index];
+ rel->lock->read_lock(rel->lock);
+ this->locked = this->index;
+ if (rel->subject)
+ {
+ /* CRL lookup is done using issuer/authkeyidentifier */
+ if (this->key == KEY_ANY && this->id &&
+ (this->cert == CERT_ANY || this->cert == CERT_X509_CRL) &&
+ rel->subject->get_type(rel->subject) == CERT_X509_CRL &&
+ rel->subject->has_issuer(rel->subject, this->id))
+ {
+ *out = rel->subject;
+ return TRUE;
+ }
+ if ((this->cert == CERT_ANY ||
+ rel->subject->get_type(rel->subject) == this->cert) &&
+ (!this->id || rel->subject->has_subject(rel->subject, this->id)))
+ {
+ if (this->key == KEY_ANY)
+ {
+ *out = rel->subject;
+ return TRUE;
+ }
+ public = rel->subject->get_public_key(rel->subject);
+ if (public)
+ {
+ if (public->get_type(public) == this->key)
+ {
+ public->destroy(public);
+ *out = rel->subject;
+ return TRUE;
+ }
+ public->destroy(public);
+ }
+ }
+ }
+ this->locked = -1;
+ rel->lock->unlock(rel->lock);
+ }
+ return FALSE;
+}
+
+/**
+ * clean up enumeration data
+ */
+static void cert_enumerator_destroy(cert_enumerator_t *this)
+{
+ relation_t *rel;
+
+ if (this->locked >= 0)
+ {
+ rel = &this->relations[this->locked];
+ rel->lock->unlock(rel->lock);
+ }
+ free(this);
+}
+
+/**
+ * implementation of credential_set_t.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_cert_cache_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+ enumerator = malloc_thing(cert_enumerator_t);
+ enumerator->public.enumerate = (void*)cert_enumerate;
+ enumerator->public.destroy = (void*)cert_enumerator_destroy;
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->relations = this->relations;
+ enumerator->index = -1;
+ enumerator->locked = -1;
+
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of cert_cache_t.flush.
+ */
+static void flush(private_cert_cache_t *this, certificate_type_t type)
+{
+ relation_t *rel;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+ if (!rel->subject)
+ {
+ continue;
+ }
+ /* check with cheap read lock first */
+ if (type != CERT_ANY)
+ {
+ rel->lock->read_lock(rel->lock);
+ if (!rel->subject || type != rel->subject->get_type(rel->subject))
+ {
+ rel->lock->unlock(rel->lock);
+ continue;
+ }
+ rel->lock->unlock(rel->lock);
+ }
+ /* double check in write lock */
+ rel->lock->write_lock(rel->lock);
+ if (rel->subject)
+ {
+ if (type == CERT_ANY || type == rel->subject->get_type(rel->subject))
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ rel->subject = NULL;
+ rel->issuer = NULL;
+ rel->hits = 0;
+ }
+ }
+ rel->lock->unlock(rel->lock);
+ }
+}
+
+/**
+ * Implementation of cert_cache_t.destroy
+ */
+static void destroy(private_cert_cache_t *this)
+{
+ relation_t *rel;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+ if (rel->subject)
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ }
+ rel->lock->destroy(rel->lock);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+cert_cache_t *cert_cache_create()
+{
+ private_cert_cache_t *this;
+ int i;
+
+ this = malloc_thing(private_cert_cache_t);
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by;
+ this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush;
+ this->public.destroy = (void(*)(cert_cache_t*))destroy;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ this->relations[i].subject = NULL;
+ this->relations[i].issuer = NULL;
+ this->relations[i].hits = 0;
+ this->relations[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/credentials/sets/cert_cache.h b/src/libcharon/credentials/sets/cert_cache.h
new file mode 100644
index 000000000..d2721866e
--- /dev/null
+++ b/src/libcharon/credentials/sets/cert_cache.h
@@ -0,0 +1,71 @@
+/*
+ * 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 cert_cache cert_cache
+ * @{ @ingroup sets
+ */
+
+#ifndef CERT_CACHE_H_
+#define CERT_CACHE_H_
+
+#include <credentials/credential_set.h>
+
+typedef struct cert_cache_t cert_cache_t;
+
+/**
+ * Certificate signature verification and certificate cache.
+ *
+ * This cache serves all certificates seen in its issued_by method
+ * and serves them as untrusted through the credential set interface. Further,
+ * it caches valid subject-issuer relationships to speed up the issued_by
+ * method.
+ */
+struct cert_cache_t {
+
+ /**
+ * Implements credential_set_t.
+ */
+ credential_set_t set;
+
+ /**
+ * Caching wrapper around certificate_t.issued_by.
+ *
+ * @param subject certificate to verify
+ * @param issuer issuing certificate to verify subject
+ * @return TRUE if subject issued by issuer
+ */
+ bool (*issued_by)(cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer);
+
+ /**
+ * Flush the certificate cache.
+ *
+ * @param type type of certificate to flush, or CERT_ANY
+ */
+ void (*flush)(cert_cache_t *this, certificate_type_t type);
+
+ /**
+ * Destroy a cert_cache instance.
+ */
+ void (*destroy)(cert_cache_t *this);
+};
+
+/**
+ * Create a cert_cache instance.
+ */
+cert_cache_t *cert_cache_create();
+
+#endif /** CERT_CACHE_H_ @}*/
diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.c b/src/libcharon/credentials/sets/ocsp_response_wrapper.c
new file mode 100644
index 000000000..82079209a
--- /dev/null
+++ b/src/libcharon/credentials/sets/ocsp_response_wrapper.c
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+#include "ocsp_response_wrapper.h"
+
+typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t;
+
+/**
+ * private data of ocsp_response_wrapper
+ */
+struct private_ocsp_response_wrapper_t {
+
+ /**
+ * public functions
+ */
+ ocsp_response_wrapper_t public;
+
+ /**
+ * wrapped OCSP response
+ */
+ ocsp_response_t *response;
+};
+
+/**
+ * enumerator for ocsp_response_wrapper_t.create_cert_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over ocsp response */
+ enumerator_t *inner;
+ /** type of cert */
+ certificate_type_t cert;
+ /** type of key */
+ key_type_t key;
+ /** filtering identity */
+ identification_t *id;
+} wrapper_enumerator_t;
+
+/**
+ * enumerate function wrapper_enumerator_t
+ */
+static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
+{
+ certificate_t *current;
+ public_key_t *public;
+
+ while (this->inner->enumerate(this->inner, &current))
+ {
+ if (this->cert != CERT_ANY && this->cert != current->get_type(current))
+ { /* CERT type requested, but does not match */
+ continue;
+ }
+ public = current->get_public_key(current);
+ if (this->key != KEY_ANY && !public)
+ { /* key type requested, but no public key */
+ DESTROY_IF(public);
+ continue;
+ }
+ if (this->key != KEY_ANY && public && this->key != public->get_type(public))
+ { /* key type requested, but public key has another type */
+ DESTROY_IF(public);
+ continue;
+ }
+ DESTROY_IF(public);
+ if (this->id && !current->has_subject(current, this->id))
+ { /* subject requested, but does not match */
+ continue;
+ }
+ *cert = current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for wrapper_enumerator_t
+ */
+static void enumerator_destroy(wrapper_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ wrapper_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+
+ enumerator = malloc_thing(wrapper_enumerator_t);
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->inner = this->response->create_cert_enumerator(this->response);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)enumerator_destroy;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of ocsp_response_wrapper_t.destroy
+ */
+static void destroy(private_ocsp_response_wrapper_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response)
+{
+ private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy;
+
+ this->response = response;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.h b/src/libcharon/credentials/sets/ocsp_response_wrapper.h
new file mode 100644
index 000000000..dc4b451df
--- /dev/null
+++ b/src/libcharon/credentials/sets/ocsp_response_wrapper.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ocsp_response_wrapper ocsp_response_wrapper
+ * @{ @ingroup sets
+ */
+
+#ifndef OCSP_RESPONSE_WRAPPER_H_
+#define OCSP_RESPONSE_WRAPPER_H_
+
+#include <credentials/credential_set.h>
+#include <credentials/certificates/ocsp_response.h>
+
+typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t;
+
+/**
+ * A wrapper around ocsp_response_t to handle it like a credential set.
+ */
+struct ocsp_response_wrapper_t {
+
+ /**
+ * implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy a ocsp_response_wrapper instance.
+ */
+ void (*destroy)(ocsp_response_wrapper_t *this);
+};
+
+/**
+ * Create a ocsp_response_wrapper instance.
+ *
+ * @param response the wrapped OCSP response
+ * @return wrapper around response
+ */
+ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response);
+
+#endif /** OCSP_RESPONSE_WRAPPER_H_ @}*/
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
new file mode 100644
index 000000000..11c94beb9
--- /dev/null
+++ b/src/libcharon/daemon.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif /* CAPABILITIES */
+
+#include "daemon.h"
+
+#include <library.h>
+#include <selectors/traffic_selector.h>
+#include <config/proposal.h>
+
+#ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+typedef struct private_daemon_t private_daemon_t;
+
+/**
+ * Private additions to daemon_t, contains threads and internal functions.
+ */
+struct private_daemon_t {
+ /**
+ * Public members of daemon_t.
+ */
+ daemon_t public;
+
+#ifdef CAPABILITIES
+ /**
+ * capabilities to keep
+ */
+ cap_t caps;
+#endif /* CAPABILITIES */
+};
+
+/**
+ * One and only instance of the daemon.
+ */
+daemon_t *charon;
+
+/**
+ * hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * we store the previous debug function so we can reset it
+ */
+static void (*dbg_old) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Logging hook for library logs, spreads debug message over bus
+ */
+static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ charon->bus->vlog(charon->bus, group, level, fmt, args);
+ va_end(args);
+}
+
+/**
+ * Clean up all daemon resources
+ */
+static void destroy(private_daemon_t *this)
+{
+ /* terminate all idle threads */
+ if (this->public.processor)
+ {
+ this->public.processor->set_threads(this->public.processor, 0);
+ }
+ /* close all IKE_SAs */
+ if (this->public.ike_sa_manager)
+ {
+ this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
+ }
+ DESTROY_IF(this->public.receiver);
+ /* unload plugins to release threads */
+ lib->plugins->unload(lib->plugins);
+#ifdef CAPABILITIES
+ cap_free(this->caps);
+#endif /* CAPABILITIES */
+ DESTROY_IF(this->public.traps);
+ DESTROY_IF(this->public.ike_sa_manager);
+ DESTROY_IF(this->public.kernel_interface);
+ DESTROY_IF(this->public.scheduler);
+ DESTROY_IF(this->public.controller);
+ DESTROY_IF(this->public.eap);
+ DESTROY_IF(this->public.sim);
+#ifdef ME
+ DESTROY_IF(this->public.connect_manager);
+ DESTROY_IF(this->public.mediation_manager);
+#endif /* ME */
+ DESTROY_IF(this->public.backends);
+ DESTROY_IF(this->public.credentials);
+ DESTROY_IF(this->public.sender);
+ DESTROY_IF(this->public.socket);
+ /* wait until all threads are gone */
+ DESTROY_IF(this->public.processor);
+
+ /* rehook library logging, shutdown logging */
+ dbg = dbg_old;
+ DESTROY_IF(this->public.bus);
+ this->public.file_loggers->destroy_offset(this->public.file_loggers,
+ offsetof(file_logger_t, destroy));
+ this->public.sys_loggers->destroy_offset(this->public.sys_loggers,
+ offsetof(sys_logger_t, destroy));
+ free(this);
+}
+
+METHOD(daemon_t, keep_cap, void,
+ private_daemon_t *this, u_int cap)
+{
+#ifdef CAPABILITIES
+ cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET);
+ cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET);
+ cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
+#endif /* CAPABILITIES */
+}
+
+METHOD(daemon_t, drop_capabilities, bool,
+ private_daemon_t *this)
+{
+#ifdef CAPABILITIES
+ if (cap_set_proc(this->caps) != 0)
+ {
+ return FALSE;
+ }
+#endif /* CAPABILITIES */
+ return TRUE;
+}
+
+METHOD(daemon_t, start, void,
+ private_daemon_t *this)
+{
+ /* start the engine, go multithreaded */
+ charon->processor->set_threads(charon->processor,
+ lib->settings->get_int(lib->settings, "charon.threads",
+ DEFAULT_THREADS));
+}
+
+/**
+ * Log loaded plugins
+ */
+static void print_plugins()
+{
+ char buf[512], *plugin;
+ int len = 0;
+ enumerator_t *enumerator;
+
+ buf[0] = '\0';
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (len < sizeof(buf) && enumerator->enumerate(enumerator, &plugin))
+ {
+ len += snprintf(&buf[len], sizeof(buf)-len, "%s ", plugin);
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_DMN, "loaded plugins: %s", buf);
+}
+
+/**
+ * Initialize logging
+ */
+static void initialize_loggers(private_daemon_t *this, bool use_stderr,
+ level_t levels[])
+{
+ sys_logger_t *sys_logger;
+ file_logger_t *file_logger;
+ enumerator_t *enumerator;
+ char *facility, *filename;
+ int loggers_defined = 0;
+ debug_t group;
+ level_t def;
+ bool append;
+ FILE *file;
+
+ /* setup sysloggers */
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "charon.syslog");
+ while (enumerator->enumerate(enumerator, &facility))
+ {
+ loggers_defined++;
+ if (streq(facility, "daemon"))
+ {
+ sys_logger = sys_logger_create(LOG_DAEMON);
+ }
+ else if (streq(facility, "auth"))
+ {
+ sys_logger = sys_logger_create(LOG_AUTHPRIV);
+ }
+ else
+ {
+ continue;
+ }
+ def = lib->settings->get_int(lib->settings,
+ "charon.syslog.%s.default", 1, facility);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ sys_logger->set_level(sys_logger, group,
+ lib->settings->get_int(lib->settings,
+ "charon.syslog.%s.%N", def,
+ facility, debug_lower_names, group));
+ }
+ this->public.sys_loggers->insert_last(this->public.sys_loggers,
+ sys_logger);
+ this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
+ }
+ enumerator->destroy(enumerator);
+
+ /* and file loggers */
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "charon.filelog");
+ while (enumerator->enumerate(enumerator, &filename))
+ {
+ loggers_defined++;
+ if (streq(filename, "stderr"))
+ {
+ file = stderr;
+ }
+ else if (streq(filename, "stdout"))
+ {
+ file = stdout;
+ }
+ else
+ {
+ append = lib->settings->get_bool(lib->settings,
+ "charon.filelog.%s.append", TRUE, filename);
+ file = fopen(filename, append ? "a" : "w");
+ if (file == NULL)
+ {
+ DBG1(DBG_DMN, "opening file %s for logging failed: %s",
+ filename, strerror(errno));
+ continue;
+ }
+ }
+ file_logger = file_logger_create(file);
+ def = lib->settings->get_int(lib->settings,
+ "charon.filelog.%s.default", 1, filename);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ file_logger->set_level(file_logger, group,
+ lib->settings->get_int(lib->settings,
+ "charon.filelog.%s.%N", def,
+ filename, debug_lower_names, group));
+ }
+ this->public.file_loggers->insert_last(this->public.file_loggers,
+ file_logger);
+ this->public.bus->add_listener(this->public.bus, &file_logger->listener);
+
+ }
+ enumerator->destroy(enumerator);
+
+ /* set up legacy style default loggers provided via command-line */
+ if (!loggers_defined)
+ {
+ /* set up default stdout file_logger */
+ file_logger = file_logger_create(stdout);
+ this->public.bus->add_listener(this->public.bus, &file_logger->listener);
+ this->public.file_loggers->insert_last(this->public.file_loggers,
+ file_logger);
+ /* set up default daemon sys_logger */
+ sys_logger = sys_logger_create(LOG_DAEMON);
+ this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
+ this->public.sys_loggers->insert_last(this->public.sys_loggers,
+ sys_logger);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ sys_logger->set_level(sys_logger, group, levels[group]);
+ if (use_stderr)
+ {
+ file_logger->set_level(file_logger, group, levels[group]);
+ }
+ }
+
+ /* set up default auth sys_logger */
+ sys_logger = sys_logger_create(LOG_AUTHPRIV);
+ this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
+ this->public.sys_loggers->insert_last(this->public.sys_loggers,
+ sys_logger);
+ sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
+ }
+}
+
+METHOD(daemon_t, initialize, bool,
+ private_daemon_t *this, bool syslog, level_t levels[])
+{
+ /* for uncritical pseudo random numbers */
+ srandom(time(NULL) + getpid());
+
+ /* setup bus and it's listeners first to enable log output */
+ this->public.bus = bus_create();
+ /* set up hook to log dbg message in library via charons message bus */
+ dbg_old = dbg;
+ dbg = dbg_bus;
+
+ initialize_loggers(this, !syslog, levels);
+
+ DBG1(DBG_DMN, "Starting IKEv2 charon daemon (strongSwan "VERSION")");
+
+ if (lib->integrity)
+ {
+ DBG1(DBG_DMN, "integrity tests enabled:");
+ DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
+ }
+
+ /* load secrets, ca certificates and crls */
+ this->public.processor = processor_create();
+ this->public.scheduler = scheduler_create();
+ this->public.credentials = credential_manager_create();
+ this->public.controller = controller_create();
+ this->public.eap = eap_manager_create();
+ this->public.sim = sim_manager_create();
+ this->public.backends = backend_manager_create();
+ this->public.kernel_interface = kernel_interface_create();
+ this->public.socket = socket_manager_create();
+ this->public.traps = trap_manager_create();
+
+ /* load plugins, further infrastructure may need it */
+ if (!lib->plugins->load(lib->plugins, NULL,
+ lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
+ {
+ return FALSE;
+ }
+
+ print_plugins();
+
+ this->public.ike_sa_manager = ike_sa_manager_create();
+ if (this->public.ike_sa_manager == NULL)
+ {
+ return FALSE;
+ }
+ this->public.sender = sender_create();
+ this->public.receiver = receiver_create();
+ if (this->public.receiver == NULL)
+ {
+ return FALSE;
+ }
+
+#ifdef ME
+ this->public.connect_manager = connect_manager_create();
+ if (this->public.connect_manager == NULL)
+ {
+ return FALSE;
+ }
+ this->public.mediation_manager = mediation_manager_create();
+#endif /* ME */
+
+ return TRUE;
+}
+
+/**
+ * Create the daemon.
+ */
+private_daemon_t *daemon_create()
+{
+ private_daemon_t *this;
+
+ INIT(this,
+ .public = {
+ .keep_cap = _keep_cap,
+ .drop_capabilities = _drop_capabilities,
+ .initialize = _initialize,
+ .start = _start,
+ .file_loggers = linked_list_create(),
+ .sys_loggers = linked_list_create(),
+ },
+ );
+
+#ifdef CAPABILITIES
+ this->caps = cap_init();
+ keep_cap(this, CAP_NET_ADMIN);
+ if (lib->leak_detective)
+ {
+ keep_cap(this, CAP_SYS_NICE);
+ }
+#endif /* CAPABILITIES */
+
+ return this;
+}
+
+/**
+ * Described in header.
+ */
+void libcharon_deinit()
+{
+
+ destroy((private_daemon_t*)charon);
+ charon = NULL;
+}
+
+/**
+ * Described in header.
+ */
+bool libcharon_init()
+{
+ private_daemon_t *this;
+
+ this = daemon_create();
+ charon = &this->public;
+
+ lib->printf_hook->add_handler(lib->printf_hook, 'R',
+ traffic_selector_printf_hook,
+ PRINTF_HOOK_ARGTYPE_POINTER,
+ PRINTF_HOOK_ARGTYPE_END);
+ lib->printf_hook->add_handler(lib->printf_hook, 'P',
+ proposal_printf_hook,
+ PRINTF_HOOK_ARGTYPE_POINTER,
+ PRINTF_HOOK_ARGTYPE_END);
+
+ if (lib->integrity &&
+ !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
+ {
+ dbg(DBG_DMN, 1, "integrity check of libcharon failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
new file mode 100644
index 000000000..9b6d97060
--- /dev/null
+++ b/src/libcharon/daemon.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup libcharon libcharon
+ *
+ * @defgroup bus bus
+ * @ingroup libcharon
+ *
+ * @defgroup listeners listeners
+ * @ingroup bus
+ *
+ * @defgroup config config
+ * @ingroup libcharon
+ *
+ * @defgroup control control
+ * @ingroup libcharon
+ *
+ * @defgroup ccredentials credentials
+ * @ingroup libcharon
+ *
+ * @defgroup sets sets
+ * @ingroup ccredentials
+ *
+ * @defgroup encoding encoding
+ * @ingroup libcharon
+ *
+ * @defgroup payloads payloads
+ * @ingroup encoding
+ *
+ * @defgroup kernel kernel
+ * @ingroup libcharon
+ *
+ * @defgroup network network
+ * @ingroup libcharon
+ *
+ * @defgroup cplugins plugins
+ * @ingroup libcharon
+ *
+ * @defgroup processing processing
+ * @ingroup libcharon
+ *
+ * @defgroup jobs jobs
+ * @ingroup processing
+ *
+ * @defgroup sa sa
+ * @ingroup libcharon
+ *
+ * @defgroup authenticators authenticators
+ * @ingroup sa
+ *
+ * @defgroup eap eap
+ * @ingroup authenticators
+ *
+ * @defgroup tasks tasks
+ * @ingroup sa
+ *
+ * @addtogroup libcharon
+ * @{
+ *
+ * IKEv2 keying daemon.
+ *
+ * All IKEv2 stuff is handled in charon. It uses a newer and more flexible
+ * architecture than pluto. Charon uses a thread-pool (called processor),
+ * which allows parallel execution SA-management. All threads originate
+ * from the processor. Work is delegated to the processor by queueing jobs
+ * to it.
+ @verbatim
+
+ +---------------------------------+ +----------------------------+
+ | controller | | config |
+ +---------------------------------+ +----------------------------+
+ | | | ^ ^ ^
+ V V V | | |
+
+ +----------+ +-----------+ +------+ +----------+ +----+
+ | receiver | | | | | +------+ | CHILD_SA | | K |
+ +---+------+ | Scheduler | | IKE- | | IKE- |--+----------+ | e |
+ | | | | SA |--| SA | | CHILD_SA | | r |
+ +------+---+ +-----------+ | | +------+ +----------+ | n |
+ <->| socket | | | Man- | | e |
+ +------+---+ +-----------+ | ager | +------+ +----------+ | l |
+ | | | | | | IKE- |--| CHILD_SA | | - |
+ +---+------+ | Processor |---| |--| SA | +----------+ | I |
+ | sender | | | | | +------+ | f |
+ +----------+ +-----------+ +------+ +----+
+
+ | | | | | |
+ V V V V V V
+ +---------------------------------+ +----------------------------+
+ | Bus | | credentials |
+ +---------------------------------+ +----------------------------+
+
+ @endverbatim
+ * The scheduler is responsible to execute timed events. Jobs may be queued to
+ * the scheduler to get executed at a defined time (e.g. rekeying). The
+ * scheduler does not execute the jobs itself, it queues them to the processor.
+ *
+ * The IKE_SA manager managers all IKE_SA. It further handles the
+ * synchronization:
+ * Each IKE_SA must be checked out strictly and checked in again after use. The
+ * manager guarantees that only one thread may check out a single IKE_SA. This
+ * allows us to write the (complex) IKE_SAs routines non-threadsave.
+ * The IKE_SA contain the state and the logic of each IKE_SA and handle the
+ * messages.
+ *
+ * The CHILD_SA contains state about a IPsec security association and manages
+ * them. An IKE_SA may have multiple CHILD_SAs. Communication to the kernel
+ * takes place here through the kernel interface.
+ *
+ * The kernel interface installs IPsec security associations, policies, routes
+ * and virtual addresses. It further provides methods to enumerate interfaces
+ * and may notify the daemon about state changes at lower layers.
+ *
+ * The bus receives signals from the different threads and relays them to
+ * interested listeners. Debugging signals, but also important state changes or
+ * error messages are sent over the bus.
+ * Its listeners are not only for logging, but also to track the state of an
+ * IKE_SA.
+ *
+ * The controller, credential_manager, bus and backend_manager (config) are
+ * places where a plugin ca register itself to privide information or observe
+ * and control the daemon.
+ */
+
+#ifndef DAEMON_H_
+#define DAEMON_H_
+
+typedef struct daemon_t daemon_t;
+
+#include <network/sender.h>
+#include <network/receiver.h>
+#include <network/socket_manager.h>
+#include <processing/scheduler.h>
+#include <processing/processor.h>
+#include <kernel/kernel_interface.h>
+#include <control/controller.h>
+#include <bus/bus.h>
+#include <bus/listeners/file_logger.h>
+#include <bus/listeners/sys_logger.h>
+#include <sa/ike_sa_manager.h>
+#include <sa/trap_manager.h>
+#include <config/backend_manager.h>
+#include <credentials/credential_manager.h>
+#include <sa/authenticators/eap/eap_manager.h>
+#include <sa/authenticators/eap/sim_manager.h>
+
+#ifdef ME
+#include <sa/connect_manager.h>
+#include <sa/mediation_manager.h>
+#endif /* ME */
+
+/**
+ * Number of threads in the thread pool, if not specified in config.
+ */
+#define DEFAULT_THREADS 16
+
+/**
+ * UDP Port on which the daemon will listen for incoming traffic.
+ */
+#define IKEV2_UDP_PORT 500
+
+/**
+ * UDP Port to which the daemon will float to if NAT is detected.
+ */
+#define IKEV2_NATT_PORT 4500
+
+/**
+ * Main class of daemon, contains some globals.
+ */
+struct daemon_t {
+
+ /**
+ * Socket manager instance
+ */
+ socket_manager_t *socket;
+
+ /**
+ * A ike_sa_manager_t instance.
+ */
+ ike_sa_manager_t *ike_sa_manager;
+
+ /**
+ * Manager for triggering policies, called traps
+ */
+ trap_manager_t *traps;
+
+ /**
+ * Manager for the different configuration backends.
+ */
+ backend_manager_t *backends;
+
+ /**
+ * Manager for the credential backends
+ */
+ credential_manager_t *credentials;
+
+ /**
+ * The Sender-Thread.
+ */
+ sender_t *sender;
+
+ /**
+ * The Receiver-Thread.
+ */
+ receiver_t *receiver;
+
+ /**
+ * The Scheduler-Thread.
+ */
+ scheduler_t *scheduler;
+
+ /**
+ * Job processing using a thread pool.
+ */
+ processor_t *processor;
+
+ /**
+ * The signaling bus.
+ */
+ bus_t *bus;
+
+ /**
+ * A list of installed file_logger_t's
+ */
+ linked_list_t *file_loggers;
+
+ /**
+ * A list of installed sys_logger_t's
+ */
+ linked_list_t *sys_loggers;
+
+ /**
+ * Kernel Interface to communicate with kernel
+ */
+ kernel_interface_t *kernel_interface;
+
+ /**
+ * Controller to control the daemon
+ */
+ controller_t *controller;
+
+ /**
+ * EAP manager to maintain registered EAP methods
+ */
+ eap_manager_t *eap;
+
+ /**
+ * SIM manager to maintain (U)SIM cards/providers
+ */
+ sim_manager_t *sim;
+
+#ifdef ME
+ /**
+ * Connect manager
+ */
+ connect_manager_t *connect_manager;
+
+ /**
+ * Mediation manager
+ */
+ mediation_manager_t *mediation_manager;
+#endif /* ME */
+
+ /**
+ * User ID the daemon will user after initialization
+ */
+ uid_t uid;
+
+ /**
+ * Group ID the daemon will use after initialization
+ */
+ gid_t gid;
+
+ /**
+ * Do not drop a given capability after initialization.
+ *
+ * Some plugins might need additional capabilites. They tell the daemon
+ * during plugin initialization which one they need, the daemon won't
+ * drop these.
+ */
+ void (*keep_cap)(daemon_t *this, u_int cap);
+
+ /**
+ * Drop all capabilities of the current process.
+ *
+ * Drops all capabalities, excect those exlcuded using keep_cap().
+ * This should be called after the initialization of the daemon because
+ * some plugins require the process to keep additional capabilities.
+ *
+ * @return TRUE if successful, FALSE otherwise
+ */
+ bool (*drop_capabilities)(daemon_t *this);
+
+ /**
+ * Initialize the daemon.
+ */
+ bool (*initialize)(daemon_t *this, bool syslog, level_t levels[]);
+
+ /**
+ * Starts the daemon, i.e. spawns the threads of the thread pool.
+ */
+ void (*start)(daemon_t *this);
+
+};
+
+/**
+ * The one and only instance of the daemon.
+ *
+ * Set between libcharon_init() and libcharon_deinit() calls.
+ */
+extern daemon_t *charon;
+
+/**
+ * Initialize libcharon and create the "charon" instance of daemon_t.
+ *
+ * @return FALSE if integrity check failed
+ */
+bool libcharon_init();
+
+/**
+ * Deinitialize libcharon and destroy the "charon" instance of daemon_t.
+ */
+void libcharon_deinit();
+
+#endif /** DAEMON_H_ @}*/
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
new file mode 100644
index 000000000..6485da492
--- /dev/null
+++ b/src/libcharon/encoding/generator.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+#include "generator.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_payload.h>
+
+
+typedef struct private_generator_t private_generator_t;
+
+/**
+ * Private part of a generator_t object.
+ */
+struct private_generator_t {
+ /**
+ * Public part of a generator_t object.
+ */
+ generator_t public;
+
+ /**
+ * Buffer used to generate the data into.
+ */
+ u_int8_t *buffer;
+
+ /**
+ * Current write position in buffer (one byte aligned).
+ */
+ u_int8_t *out_position;
+
+ /**
+ * Position of last byte in buffer.
+ */
+ u_int8_t *roof_position;
+
+ /**
+ * Current bit writing to in current byte (between 0 and 7).
+ */
+ u_int8_t current_bit;
+
+ /**
+ * Associated data struct to read informations from.
+ */
+ void *data_struct;
+
+ /*
+ * Last payload length position offset in the buffer.
+ */
+ u_int32_t last_payload_length_position_offset;
+
+ /**
+ * Offset of the header length field in the buffer.
+ */
+ u_int32_t header_length_position_offset;
+
+ /**
+ * Last SPI size.
+ */
+ u_int8_t last_spi_size;
+
+ /**
+ * Attribute format of the last generated transform attribute.
+ *
+ * Used to check if a variable value field is used or not for
+ * the transform attribute value.
+ */
+ bool attribute_format;
+
+ /**
+ * Depending on the value of attribute_format this field is used
+ * to hold the length of the transform attribute in bytes.
+ */
+ u_int16_t attribute_length;
+};
+
+/**
+ * Get size of current buffer in bytes.
+ */
+static int get_size(private_generator_t *this)
+{
+ return this->roof_position - this->buffer;
+}
+
+/**
+ * Get free space of current buffer in bytes.
+ */
+static int get_space(private_generator_t *this)
+{
+ return this->roof_position - this->out_position;
+}
+
+/**
+ * Get length of data in buffer (in bytes).
+ */
+static int get_length(private_generator_t *this)
+{
+ return this->out_position - this->buffer;
+}
+
+/**
+ * Get current offset in buffer (in bytes).
+ */
+static u_int32_t get_offset(private_generator_t *this)
+{
+ return this->out_position - this->buffer;
+}
+
+/**
+ * Makes sure enough space is available in buffer to store amount of bits.
+ */
+static void make_space_available(private_generator_t *this, int bits)
+{
+ while ((get_space(this) * 8 - this->current_bit) < bits)
+ {
+ int old_buffer_size, new_buffer_size, out_position_offset;
+
+ old_buffer_size = get_size(this);
+ new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
+ out_position_offset = this->out_position - this->buffer;
+
+ DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
+ old_buffer_size, new_buffer_size);
+
+ this->buffer = realloc(this->buffer,new_buffer_size);
+ this->out_position = (this->buffer + out_position_offset);
+ this->roof_position = (this->buffer + new_buffer_size);
+ }
+}
+
+/**
+ * Writes a specific amount of byte into the buffer.
+ */
+static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
+ int number_of_bytes)
+{
+ int i;
+ u_int8_t *read_position = (u_int8_t *)bytes;
+
+ make_space_available(this, number_of_bytes * 8);
+
+ for (i = 0; i < number_of_bytes; i++)
+ {
+ *(this->out_position) = *(read_position);
+ read_position++;
+ this->out_position++;
+ }
+}
+
+/**
+ * Writes a specific amount of byte into the buffer at a specific offset.
+ */
+static void write_bytes_to_buffer_at_offset(private_generator_t *this,
+ void *bytes, int number_of_bytes, u_int32_t offset)
+{
+ int i;
+ u_int8_t *read_position = (u_int8_t *)bytes;
+ u_int8_t *write_position;
+ u_int32_t free_space_after_offset = get_size(this) - offset;
+
+ /* check first if enough space for new data is available */
+ if (number_of_bytes > free_space_after_offset)
+ {
+ make_space_available(this,
+ (number_of_bytes - free_space_after_offset) * 8);
+ }
+
+ write_position = this->buffer + offset;
+ for (i = 0; i < number_of_bytes; i++)
+ {
+ *write_position = *read_position;
+ read_position++;
+ write_position++;
+ }
+}
+
+/**
+ * Generates a U_INT-Field type and writes it to buffer.
+ */
+static void generate_u_int_type(private_generator_t *this,
+ encoding_type_t int_type,u_int32_t offset)
+{
+ int number_of_bits = 0;
+
+ /* find out number of bits of each U_INT type to check for enough space */
+ switch (int_type)
+ {
+ case U_INT_4:
+ number_of_bits = 4;
+ break;
+ case TS_TYPE:
+ case U_INT_8:
+ number_of_bits = 8;
+ break;
+ case U_INT_16:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ number_of_bits = 16;
+ break;
+ case U_INT_32:
+ number_of_bits = 32;
+ break;
+ case ATTRIBUTE_TYPE:
+ number_of_bits = 15;
+ break;
+ case IKE_SPI:
+ number_of_bits = 64;
+ break;
+ default:
+ DBG1(DBG_ENC, "U_INT Type %N is not supported",
+ encoding_type_names, int_type);
+ return;
+ }
+ if ((number_of_bits % 8) == 0 && this->current_bit != 0)
+ {
+ DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
+ encoding_type_names, int_type);
+ return;
+ }
+
+ make_space_available(this, number_of_bits);
+ switch (int_type)
+ {
+ case U_INT_4:
+ {
+ u_int8_t high, low;
+
+ if (this->current_bit == 0)
+ {
+ /* high of current byte in buffer has to be set to the new value*/
+ high = *((u_int8_t *)(this->data_struct + offset)) << 4;
+ /* low in buffer is not changed */
+ low = *(this->out_position) & 0x0F;
+ /* high is set, low_val is not changed */
+ *(this->out_position) = high | low;
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ /* write position is not changed, just bit position is moved */
+ this->current_bit = 4;
+ }
+ else if (this->current_bit == 4)
+ {
+ /* high in buffer is not changed */
+ high = *(this->out_position) & 0xF0;
+ /* low of current byte in buffer has to be set to the new value*/
+ low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
+ *(this->out_position) = high | low;
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ this->out_position++;
+ this->current_bit = 0;
+ }
+ else
+ {
+ DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
+ /* 4 Bit integers must have a 4 bit alignment */
+ return;
+ }
+ break;
+ }
+ case TS_TYPE:
+ case U_INT_8:
+ {
+ /* 8 bit values are written as they are */
+ *this->out_position = *((u_int8_t *)(this->data_struct + offset));
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ this->out_position++;
+ break;
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ u_int8_t attribute_format_flag;
+ u_int16_t val;
+
+ /* attribute type must not change first bit of current byte */
+ if (this->current_bit != 1)
+ {
+ DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
+ return;
+ }
+ attribute_format_flag = *(this->out_position) & 0x80;
+ /* get attribute type value as 16 bit integer*/
+ val = *((u_int16_t*)(this->data_struct + offset));
+ /* unset most significant bit */
+ val &= 0x7FFF;
+ if (attribute_format_flag)
+ {
+ val |= 0x8000;
+ }
+ val = htons(val);
+ DBG3(DBG_ENC, " => %d", val);
+ /* write bytes to buffer (set bit is overwritten) */
+ write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
+ this->current_bit = 0;
+ break;
+
+ }
+ case U_INT_16:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
+ DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
+ write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
+ break;
+ }
+ case U_INT_32:
+ {
+ u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
+ DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
+ write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
+ break;
+ }
+ case IKE_SPI:
+ {
+ /* 64 bit are written as-is, no host order conversion */
+ write_bytes_to_buffer(this, this->data_struct + offset,
+ sizeof(u_int64_t));
+ DBG3(DBG_ENC, " => %b", this->data_struct + offset,
+ sizeof(u_int64_t));
+ break;
+ }
+ default:
+ {
+ DBG1(DBG_ENC, "U_INT Type %N is not supported",
+ encoding_type_names, int_type);
+ return;
+ }
+ }
+}
+
+/**
+ * Generate a reserved bit or byte
+ */
+static void generate_reserved_field(private_generator_t *this, int bits)
+{
+ /* only one bit or 8 bit fields are supported */
+ if (bits != 1 && bits != 8)
+ {
+ DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits);
+ return ;
+ }
+ make_space_available(this, bits);
+
+ if (bits == 1)
+ {
+ u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
+
+ *(this->out_position) = *(this->out_position) & reserved_bit;
+ if (this->current_bit == 0)
+ {
+ /* memory must be zero */
+ *(this->out_position) = 0x00;
+ }
+ this->current_bit++;
+ if (this->current_bit >= 8)
+ {
+ this->current_bit = this->current_bit % 8;
+ this->out_position++;
+ }
+ }
+ else
+ {
+ if (this->current_bit > 0)
+ {
+ DBG1(DBG_ENC, "reserved field cannot be written cause "
+ "alignement of current bit is %d", this->current_bit);
+ return;
+ }
+ *(this->out_position) = 0x00;
+ this->out_position++;
+ }
+}
+
+/**
+ * Generate a FLAG filed
+ */
+static void generate_flag(private_generator_t *this, u_int32_t offset)
+{
+ u_int8_t flag_value;
+ u_int8_t flag;
+
+ flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
+ /* get flag position */
+ flag = (flag_value << (7 - this->current_bit));
+
+ /* make sure one bit is available in buffer */
+ make_space_available(this, 1);
+ if (this->current_bit == 0)
+ {
+ /* memory must be zero */
+ *(this->out_position) = 0x00;
+ }
+
+ *(this->out_position) = *(this->out_position) | flag;
+ DBG3(DBG_ENC, " => %d", *this->out_position);
+
+ this->current_bit++;
+ if (this->current_bit >= 8)
+ {
+ this->current_bit = this->current_bit % 8;
+ this->out_position++;
+ }
+}
+
+/**
+ * Generates a bytestream from a chunk_t.
+ */
+static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
+{
+ chunk_t *value;
+
+ if (this->current_bit != 0)
+ {
+ DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
+ return ;
+ }
+
+ value = (chunk_t *)(this->data_struct + offset);
+ DBG3(DBG_ENC, " => %B", value);
+
+ write_bytes_to_buffer(this, value->ptr, value->len);
+}
+
+/**
+ * Implementation of private_generator_t.write_to_chunk.
+ */
+static void write_to_chunk(private_generator_t *this,chunk_t *data)
+{
+ int data_length = get_length(this);
+ u_int32_t header_length_field = data_length;
+
+ /* write length into header length field */
+ if (this->header_length_position_offset > 0)
+ {
+ u_int32_t val = htonl(header_length_field);
+ write_bytes_to_buffer_at_offset(this, &val, sizeof(u_int32_t),
+ this->header_length_position_offset);
+ }
+
+ if (this->current_bit > 0)
+ {
+ data_length++;
+ }
+ *data = chunk_alloc(data_length);
+ memcpy(data->ptr, this->buffer, data_length);
+
+ DBG3(DBG_ENC, "generated data of this generator %B", data);
+}
+
+/**
+ * Implementation of private_generator_t.generate_payload.
+ */
+static void generate_payload (private_generator_t *this,payload_t *payload)
+{
+ int i, offset_start;
+ size_t rule_count;
+ encoding_rule_t *rules;
+ payload_type_t payload_type;
+
+ this->data_struct = payload;
+ payload_type = payload->get_type(payload);
+ /* spi size has to get reseted */
+ this->last_spi_size = 0;
+
+ offset_start = this->out_position - this->buffer;
+
+ DBG2(DBG_ENC, "generating payload of type %N",
+ payload_type_names, payload_type);
+
+ /* each payload has its own encoding rules */
+ payload->get_encoding_rules(payload, &rules, &rule_count);
+
+ for (i = 0; i < rule_count;i++)
+ {
+ DBG2(DBG_ENC, " generating rule %d %N",
+ i, encoding_type_names, rules[i].type);
+ switch (rules[i].type)
+ {
+ case U_INT_4:
+ case U_INT_8:
+ case U_INT_16:
+ case U_INT_32:
+ case IKE_SPI:
+ case TS_TYPE:
+ case ATTRIBUTE_TYPE:
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ generate_u_int_type(this, rules[i].type, rules[i].offset);
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ generate_reserved_field(this, 1);
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ generate_reserved_field(this, 8);
+ break;
+ }
+ case FLAG:
+ {
+ generate_flag(this, rules[i].offset);
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ this->last_payload_length_position_offset = get_offset(this);
+ generate_u_int_type(this, U_INT_16,rules[i].offset);
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ this->header_length_position_offset = get_offset(this);
+ generate_u_int_type(this ,U_INT_32, rules[i].offset);
+ break;
+ }
+ case SPI_SIZE:
+ generate_u_int_type(this, U_INT_8, rules[i].offset);
+ this->last_spi_size = *((u_int8_t *)(this->data_struct +
+ rules[i].offset));
+ break;
+ case ADDRESS:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ case SPI:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ case NOTIFICATION_DATA:
+ case NONCE_DATA:
+ case ID_DATA:
+ case AUTH_DATA:
+ case CERT_DATA:
+ case CERTREQ_DATA:
+ case SPIS:
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ case VID_DATA:
+ case EAP_DATA:
+ {
+ u_int32_t payload_length_position_offset;
+ u_int16_t length_of_payload;
+ u_int16_t header_length = 0;
+ u_int16_t length_in_network_order;
+
+ switch(rules[i].type)
+ {
+ case KEY_EXCHANGE_DATA:
+ header_length = KE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case NOTIFICATION_DATA:
+ header_length = NOTIFY_PAYLOAD_HEADER_LENGTH +
+ this->last_spi_size;
+ break;
+ case NONCE_DATA:
+ header_length = NONCE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case ID_DATA:
+ header_length = ID_PAYLOAD_HEADER_LENGTH;
+ break;
+ case AUTH_DATA:
+ header_length = AUTH_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CERT_DATA:
+ header_length = CERT_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CERTREQ_DATA:
+ header_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
+ break;
+ case SPIS:
+ header_length = DELETE_PAYLOAD_HEADER_LENGTH;
+ break;
+ case VID_DATA:
+ header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
+ break;
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
+ break;
+ case EAP_DATA:
+ header_length = EAP_PAYLOAD_HEADER_LENGTH;
+ break;
+ default:
+ break;
+ }
+ generate_from_chunk(this, rules[i].offset);
+
+ payload_length_position_offset =
+ this->last_payload_length_position_offset;
+
+ length_of_payload = header_length +
+ ((chunk_t *)(this->data_struct + rules[i].offset))->len;
+
+ length_in_network_order = htons(length_of_payload);
+ write_bytes_to_buffer_at_offset(this, &length_in_network_order,
+ sizeof(u_int16_t), payload_length_position_offset);
+ break;
+ }
+ case PROPOSALS:
+ {
+ u_int32_t payload_length_position_offset =
+ this->last_payload_length_position_offset;
+ /* Length of SA_PAYLOAD is calculated */
+ u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *proposals = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_proposal;
+
+ iterator = proposals->create_iterator(proposals,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_proposal))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_proposal);
+ after_generate_position_offset = get_offset(this);
+ length_of_sa_payload += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_sa_payload);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),payload_length_position_offset);
+ break;
+ }
+ case TRANSFORMS:
+ {
+ u_int32_t payload_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_proposal =
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
+ u_int16_t int16_val;
+ linked_list_t *transforms = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_transform;
+
+ iterator = transforms->create_iterator(transforms,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_transform))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_transform);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_proposal += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_proposal);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t), payload_length_position_offset);
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ u_int32_t transform_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_transform =
+ TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *transform_attributes =*((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_attribute;
+
+ iterator = transform_attributes->create_iterator(
+ transform_attributes, TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_attribute);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_transform += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_transform);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),transform_length_position_offset);
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTES:
+ {
+ u_int32_t configurations_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *configuration_attributes = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_attribute;
+
+ iterator = configuration_attributes->create_iterator(
+ configuration_attributes,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_attribute);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_configurations += after_generate_position_offset -
+ before_generate_position_offset;
+ }
+
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_configurations);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),configurations_length_position_offset);
+ break;
+ }
+ case ATTRIBUTE_FORMAT:
+ {
+ generate_flag(this, rules[i].offset);
+ /* Attribute format is a flag which is stored in context*/
+ this->attribute_format =
+ *((bool *)(this->data_struct + rules[i].offset));
+ break;
+ }
+
+ case ATTRIBUTE_LENGTH_OR_VALUE:
+ {
+ if (this->attribute_format == FALSE)
+ {
+ generate_u_int_type(this, U_INT_16, rules[i].offset);
+ /* this field hold the length of the attribute */
+ this->attribute_length =
+ *((u_int16_t *)(this->data_struct + rules[i].offset));
+ }
+ else
+ {
+ generate_u_int_type(this, U_INT_16, rules[i].offset);
+ }
+ break;
+ }
+ case ATTRIBUTE_VALUE:
+ {
+ if (this->attribute_format == FALSE)
+ {
+ DBG2(DBG_ENC, "attribute value has not fixed size");
+ /* the attribute value is generated */
+ generate_from_chunk(this, rules[i].offset);
+ }
+ break;
+ }
+ case TRAFFIC_SELECTORS:
+ {
+ u_int32_t payload_length_position_offset =
+ this->last_payload_length_position_offset;
+ u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
+ u_int16_t int16_val;
+ linked_list_t *traffic_selectors = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ iterator_t *iterator;
+ payload_t *current_tss;
+
+ iterator = traffic_selectors->create_iterator(
+ traffic_selectors,TRUE);
+ while (iterator->iterate(iterator, (void **)&current_tss))
+ {
+ u_int32_t before_generate_position_offset;
+ u_int32_t after_generate_position_offset;
+
+ before_generate_position_offset = get_offset(this);
+ generate_payload(this, current_tss);
+ after_generate_position_offset = get_offset(this);
+
+ length_of_ts_payload += (after_generate_position_offset -
+ before_generate_position_offset);
+ }
+ iterator->destroy(iterator);
+
+ int16_val = htons(length_of_ts_payload);
+ write_bytes_to_buffer_at_offset(this, &int16_val,
+ sizeof(u_int16_t),payload_length_position_offset);
+ break;
+ }
+
+ case ENCRYPTED_DATA:
+ {
+ generate_from_chunk(this, rules[i].offset);
+ break;
+ }
+ default:
+ DBG1(DBG_ENC, "field type %N is not supported",
+ encoding_type_names, rules[i].type);
+ return;
+ }
+ }
+ DBG2(DBG_ENC, "generating %N payload finished",
+ payload_type_names, payload_type);
+ DBG3(DBG_ENC, "generated data for this payload %b",
+ this->buffer + offset_start,
+ this->out_position - this->buffer - offset_start);
+}
+
+/**
+ * Implementation of generator_t.destroy.
+ */
+static status_t destroy(private_generator_t *this)
+{
+ free(this->buffer);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+generator_t *generator_create()
+{
+ private_generator_t *this;
+
+ this = malloc_thing(private_generator_t);
+
+ /* initiate public functions */
+ this->public.generate_payload = (void(*)(generator_t*, payload_t *))generate_payload;
+ this->public.destroy = (void(*)(generator_t*)) destroy;
+ this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *))write_to_chunk;
+
+ /* allocate memory for buffer */
+ this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE);
+
+ /* initiate private variables */
+ this->out_position = this->buffer;
+ this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
+ this->data_struct = NULL;
+ this->current_bit = 0;
+ this->last_payload_length_position_offset = 0;
+ this->header_length_position_offset = 0;
+ this->attribute_format = FALSE;
+ this->attribute_length = 0;
+
+ return &(this->public);
+}
+
diff --git a/src/libcharon/encoding/generator.h b/src/libcharon/encoding/generator.h
new file mode 100644
index 000000000..2221c84af
--- /dev/null
+++ b/src/libcharon/encoding/generator.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup generator generator
+ * @{ @ingroup encoding
+ */
+
+#ifndef GENERATOR_H_
+#define GENERATOR_H_
+
+typedef struct generator_t generator_t;
+
+#include <library.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Generating is done in a data buffer.
+ * This is the start size of this buffer in bytes.
+ */
+#define GENERATOR_DATA_BUFFER_SIZE 500
+
+/**
+ * Number of bytes to increase the buffer, if it is too small.
+ */
+#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
+
+
+/**
+ * A generator_t class used to generate IKEv2 payloads.
+ *
+ * After creation, multiple payloads can be generated with the generate_payload
+ * method. The generated bytes are appended. After all payloads are added,
+ * the write_to_chunk method writes out all generated data since
+ * the creation of the generator. After that, the generator must be destroyed.
+ * The generater uses a set of encoding rules, which it can get from
+ * the supplied payload. With this rules, the generater can generate
+ * the payload and all substructures automatically.
+ */
+struct generator_t {
+
+ /**
+ * Generates a specific payload from given payload object.
+ *
+ * Remember: Header and substructures are also handled as payloads.
+ *
+ * @param payload interface payload_t implementing object
+ */
+ void (*generate_payload) (generator_t *this,payload_t *payload);
+
+ /**
+ * Writes all generated data of the generator to a chunk.
+ *
+ * @param data chunk to write the data to
+ */
+ void (*write_to_chunk) (generator_t *this,chunk_t *data);
+
+ /**
+ * Destroys a generator_t object.
+ */
+ void (*destroy) (generator_t *this);
+};
+
+/**
+ * Constructor to create a generator.
+ *
+ * @return generator_t object.
+ */
+generator_t *generator_create(void);
+
+#endif /** GENERATOR_H_ @}*/
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
new file mode 100644
index 000000000..acfc0fd44
--- /dev/null
+++ b/src/libcharon/encoding/message.c
@@ -0,0 +1,1723 @@
+/*
+ * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "message.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <sa/ike_sa_id.h>
+#include <encoding/generator.h>
+#include <encoding/parser.h>
+#include <utils/linked_list.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+
+/**
+ * Max number of notify payloads per IKEv2 Message
+ */
+#define MAX_NOTIFY_PAYLOADS 20
+
+/**
+ * Max number of delete payloads per IKEv2 Message
+ */
+#define MAX_DELETE_PAYLOADS 20
+
+
+typedef struct payload_rule_t payload_rule_t;
+
+/**
+ * A payload rule defines the rules for a payload
+ * in a specific message rule. It defines if and how
+ * many times a payload must/can occur in a message
+ * and if it must be encrypted.
+ */
+struct payload_rule_t {
+ /**
+ * Payload type.
+ */
+ payload_type_t payload_type;
+
+ /**
+ * Minimal occurence of this payload.
+ */
+ size_t min_occurence;
+
+ /**
+ * Max occurence of this payload.
+ */
+ size_t max_occurence;
+
+ /**
+ * TRUE if payload must be encrypted
+ */
+ bool encrypted;
+
+ /**
+ * If this payload occurs, the message rule is
+ * fullfilled in any case. This applies e.g. to
+ * notify_payloads.
+ */
+ bool sufficient;
+};
+
+typedef struct payload_order_t payload_order_t;
+
+/**
+ * payload ordering structure allows us to reorder payloads according to RFC.
+ */
+struct payload_order_t {
+
+ /**
+ * payload type
+ */
+ payload_type_t type;
+
+ /**
+ * notify type, if payload == NOTIFY
+ */
+ notify_type_t notify;
+};
+
+
+typedef struct message_rule_t message_rule_t;
+
+/**
+ * A message rule defines the kind of a message,
+ * if it has encrypted contents and a list
+ * of payload ordering rules and payload parsing rules.
+ */
+struct message_rule_t {
+ /**
+ * Type of message.
+ */
+ exchange_type_t exchange_type;
+
+ /**
+ * Is message a request or response.
+ */
+ bool is_request;
+
+ /**
+ * Message contains encrypted content.
+ */
+ bool encrypted_content;
+
+ /**
+ * Number of payload rules which will follow
+ */
+ int payload_rule_count;
+
+ /**
+ * Pointer to first payload rule
+ */
+ payload_rule_t *payload_rules;
+
+ /**
+ * Number of payload order rules
+ */
+ int payload_order_count;
+
+ /**
+ * payload ordering rules
+ */
+ payload_order_t *payload_order;
+};
+
+/**
+ * Message rule for IKE_SA_INIT from initiator.
+ */
+static payload_rule_t ike_sa_init_i_payload_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, 10, FALSE, FALSE},
+};
+
+/**
+ * payload order for IKE_SA_INIT initiator
+ */
+static payload_order_t ike_sa_init_i_payload_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},
+};
+
+/**
+ * Message rule for IKE_SA_INIT from responder.
+ */
+static payload_rule_t ike_sa_init_r_payload_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},
+ {VENDOR_ID, 0, 10, FALSE, FALSE},
+};
+
+/**
+ * payload order for IKE_SA_INIT responder
+ */
+static payload_order_t ike_sa_init_r_payload_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},
+};
+
+/**
+ * Message rule for IKE_AUTH from initiator.
+ */
+static payload_rule_t ike_auth_i_payload_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, 4, TRUE, FALSE},
+ {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE},
+ {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},
+#else
+ {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
+#endif /* ME */
+ {CONFIGURATION, 0, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for IKE_AUTH initiator
+ */
+static payload_order_t ike_auth_i_payload_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},
+};
+
+/**
+ * Message rule for IKE_AUTH from responder.
+ */
+static payload_rule_t ike_auth_r_payload_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, 4, 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, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for IKE_AUTH responder
+ */
+static payload_order_t ike_auth_r_payload_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},
+};
+
+/**
+ * Message rule for INFORMATIONAL from initiator.
+ */
+static payload_rule_t informational_i_payload_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, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL initiator
+ */
+static payload_order_t informational_i_payload_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},
+};
+
+/**
+ * Message rule for INFORMATIONAL from responder.
+ */
+static payload_rule_t informational_r_payload_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, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL responder
+ */
+static payload_order_t informational_r_payload_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},
+};
+
+/**
+ * Message rule for CREATE_CHILD_SA from initiator.
+ */
+static payload_rule_t create_child_sa_i_payload_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, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for CREATE_CHILD_SA from initiator.
+ */
+static payload_order_t create_child_sa_i_payload_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},
+};
+
+/**
+ * Message rule for CREATE_CHILD_SA from responder.
+ */
+static payload_rule_t create_child_sa_r_payload_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, 10, TRUE, FALSE},
+};
+
+/**
+ * payload order for CREATE_CHILD_SA from responder.
+ */
+static payload_order_t create_child_sa_r_payload_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},
+};
+
+#ifdef ME
+/**
+ * Message rule for ME_CONNECT from initiator.
+ */
+static payload_rule_t me_connect_i_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {ID_PEER, 1, 1, TRUE, FALSE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE}
+};
+
+/**
+ * payload order for ME_CONNECT from initiator.
+ */
+static payload_order_t me_connect_i_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, 0},
+ {ID_PEER, 0},
+ {VENDOR_ID, 0},
+};
+
+/**
+ * Message rule for ME_CONNECT from responder.
+ */
+static payload_rule_t me_connect_r_payload_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
+ {VENDOR_ID, 0, 10, TRUE, FALSE}
+};
+
+/**
+ * payload order for ME_CONNECT from responder.
+ */
+static payload_order_t me_connect_r_payload_order[] = {
+/* payload type notify type */
+ {NOTIFY, 0},
+ {VENDOR_ID, 0},
+};
+#endif /* ME */
+
+/**
+ * Message rules, defines allowed payloads.
+ */
+static message_rule_t message_rules[] = {
+ {IKE_SA_INIT, TRUE, FALSE,
+ (sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),
+ ike_sa_init_i_payload_rules,
+ (sizeof(ike_sa_init_i_payload_order)/sizeof(payload_order_t)),
+ ike_sa_init_i_payload_order,
+ },
+ {IKE_SA_INIT, FALSE, FALSE,
+ (sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),
+ ike_sa_init_r_payload_rules,
+ (sizeof(ike_sa_init_r_payload_order)/sizeof(payload_order_t)),
+ ike_sa_init_r_payload_order,
+ },
+ {IKE_AUTH, TRUE, TRUE,
+ (sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),
+ ike_auth_i_payload_rules,
+ (sizeof(ike_auth_i_payload_order)/sizeof(payload_order_t)),
+ ike_auth_i_payload_order,
+ },
+ {IKE_AUTH, FALSE, TRUE,
+ (sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),
+ ike_auth_r_payload_rules,
+ (sizeof(ike_auth_r_payload_order)/sizeof(payload_order_t)),
+ ike_auth_r_payload_order,
+ },
+ {INFORMATIONAL, TRUE, TRUE,
+ (sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),
+ informational_i_payload_rules,
+ (sizeof(informational_i_payload_order)/sizeof(payload_order_t)),
+ informational_i_payload_order,
+ },
+ {INFORMATIONAL, FALSE, TRUE,
+ (sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),
+ informational_r_payload_rules,
+ (sizeof(informational_r_payload_order)/sizeof(payload_order_t)),
+ informational_r_payload_order,
+ },
+ {CREATE_CHILD_SA, TRUE, TRUE,
+ (sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)),
+ create_child_sa_i_payload_rules,
+ (sizeof(create_child_sa_i_payload_order)/sizeof(payload_order_t)),
+ create_child_sa_i_payload_order,
+ },
+ {CREATE_CHILD_SA, FALSE, TRUE,
+ (sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)),
+ create_child_sa_r_payload_rules,
+ (sizeof(create_child_sa_r_payload_order)/sizeof(payload_order_t)),
+ create_child_sa_r_payload_order,
+ },
+#ifdef ME
+ {ME_CONNECT, TRUE, TRUE,
+ (sizeof(me_connect_i_payload_rules)/sizeof(payload_rule_t)),
+ me_connect_i_payload_rules,
+ (sizeof(me_connect_i_payload_order)/sizeof(payload_order_t)),
+ me_connect_i_payload_order,
+ },
+ {ME_CONNECT, FALSE, TRUE,
+ (sizeof(me_connect_r_payload_rules)/sizeof(payload_rule_t)),
+ me_connect_r_payload_rules,
+ (sizeof(me_connect_r_payload_order)/sizeof(payload_order_t)),
+ me_connect_r_payload_order,
+ },
+#endif /* ME */
+};
+
+
+typedef struct private_message_t private_message_t;
+
+/**
+ * Private data of an message_t object.
+ */
+struct private_message_t {
+
+ /**
+ * Public part of a message_t object.
+ */
+ message_t public;
+
+ /**
+ * Minor version of message.
+ */
+ u_int8_t major_version;
+
+ /**
+ * Major version of message.
+ */
+ u_int8_t minor_version;
+
+ /**
+ * First Payload in message.
+ */
+ payload_type_t first_payload;
+
+ /**
+ * Assigned exchange type.
+ */
+ exchange_type_t exchange_type;
+
+ /**
+ * TRUE if message is a request, FALSE if a reply.
+ */
+ bool is_request;
+
+ /**
+ * Message ID of this message.
+ */
+ u_int32_t message_id;
+
+ /**
+ * ID of assigned IKE_SA.
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * Assigned UDP packet, stores incoming packet or last generated one.
+ */
+ packet_t *packet;
+
+ /**
+ * Linked List where payload data are stored in.
+ */
+ linked_list_t *payloads;
+
+ /**
+ * Assigned parser to parse Header and Body of this message.
+ */
+ parser_t *parser;
+
+ /**
+ * The message rule for this message instance
+ */
+ message_rule_t *message_rule;
+};
+
+/**
+ * Implementation of private_message_t.set_message_rule.
+ */
+static status_t set_message_rule(private_message_t *this)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++)
+ {
+ if ((this->exchange_type == message_rules[i].exchange_type) &&
+ (this->is_request == message_rules[i].is_request))
+ {
+ /* found rule for given exchange_type*/
+ this->message_rule = &(message_rules[i]);
+ return SUCCESS;
+ }
+ }
+ this->message_rule = NULL;
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of private_message_t.get_payload_rule.
+ */
+static status_t get_payload_rule(private_message_t *this,
+ payload_type_t payload_type, payload_rule_t **payload_rule)
+{
+ int i;
+
+ for (i = 0; i < this->message_rule->payload_rule_count;i++)
+ {
+ if (this->message_rule->payload_rules[i].payload_type == payload_type)
+ {
+ *payload_rule = &(this->message_rule->payload_rules[i]);
+ return SUCCESS;
+ }
+ }
+
+ *payload_rule = NULL;
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of message_t.set_ike_sa_id.
+ */
+static void set_ike_sa_id(private_message_t *this,ike_sa_id_t *ike_sa_id)
+{
+ DESTROY_IF(this->ike_sa_id);
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+}
+
+/**
+ * Implementation of message_t.get_ike_sa_id.
+ */
+static ike_sa_id_t* get_ike_sa_id(private_message_t *this)
+{
+ return this->ike_sa_id;
+}
+
+/**
+ * Implementation of message_t.set_message_id.
+ */
+static void set_message_id(private_message_t *this,u_int32_t message_id)
+{
+ this->message_id = message_id;
+}
+
+/**
+ * Implementation of message_t.get_message_id.
+ */
+static u_int32_t get_message_id(private_message_t *this)
+{
+ return this->message_id;
+}
+
+/**
+ * Implementation of message_t.get_initiator_spi.
+ */
+static u_int64_t get_initiator_spi(private_message_t *this)
+{
+ return (this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
+}
+
+/**
+ * Implementation of message_t.get_responder_spi.
+ */
+static u_int64_t get_responder_spi(private_message_t *this)
+{
+ return (this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+}
+
+/**
+ * Implementation of message_t.set_major_version.
+ */
+static void set_major_version(private_message_t *this,u_int8_t major_version)
+{
+ this->major_version = major_version;
+}
+
+/**
+ * Implementation of message_t.set_major_version.
+ */
+static u_int8_t get_major_version(private_message_t *this)
+{
+ return this->major_version;
+}
+
+/**
+ * Implementation of message_t.set_minor_version.
+ */
+static void set_minor_version(private_message_t *this,u_int8_t minor_version)
+{
+ this->minor_version = minor_version;
+}
+
+/**
+ * Implementation of message_t.get_minor_version.
+ */
+static u_int8_t get_minor_version(private_message_t *this)
+{
+ return this->minor_version;
+}
+
+/**
+ * Implementation of message_t.set_exchange_type.
+ */
+static void set_exchange_type(private_message_t *this,
+ exchange_type_t exchange_type)
+{
+ this->exchange_type = exchange_type;
+}
+
+/**
+ * Implementation of message_t.get_exchange_type.
+ */
+static exchange_type_t get_exchange_type(private_message_t *this)
+{
+ return this->exchange_type;
+}
+
+/**
+ * Implementation of message_t.get_first_payload_type.
+ */
+static payload_type_t get_first_payload_type(private_message_t *this)
+{
+ return this->first_payload;
+}
+
+/**
+ * Implementation of message_t.set_request.
+ */
+static void set_request(private_message_t *this, bool request)
+{
+ this->is_request = request;
+}
+
+/**
+ * Implementation of message_t.get_request.
+ */
+static exchange_type_t get_request(private_message_t *this)
+{
+ return this->is_request;
+}
+
+/**
+ * Is this message in an encoded form?
+ */
+static bool is_encoded(private_message_t *this)
+{
+ chunk_t data = this->packet->get_data(this->packet);
+
+ if (data.ptr == NULL)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of message_t.add_payload.
+ */
+static void add_payload(private_message_t *this, payload_t *payload)
+{
+ payload_t *last_payload;
+
+ if (this->payloads->get_count(this->payloads) > 0)
+ {
+ this->payloads->get_last(this->payloads, (void **)&last_payload);
+ last_payload->set_next_type(last_payload, payload->get_type(payload));
+ }
+ else
+ {
+ this->first_payload = payload->get_type(payload);
+ }
+ payload->set_next_type(payload, NO_PAYLOAD);
+ this->payloads->insert_last(this->payloads, payload);
+
+ DBG2(DBG_ENC ,"added payload of type %N to message",
+ payload_type_names, payload->get_type(payload));
+}
+
+/**
+ * Implementation of message_t.add_notify.
+ */
+static void add_notify(private_message_t *this, bool flush, notify_type_t type,
+ chunk_t data)
+{
+ notify_payload_t *notify;
+ payload_t *payload;
+
+ if (flush)
+ {
+ while (this->payloads->remove_last(this->payloads,
+ (void**)&payload) == SUCCESS)
+ {
+ payload->destroy(payload);
+ }
+ }
+ notify = notify_payload_create();
+ notify->set_notify_type(notify, type);
+ notify->set_notification_data(notify, data);
+ add_payload(this, (payload_t*)notify);
+}
+
+/**
+ * Implementation of message_t.set_source.
+ */
+static void set_source(private_message_t *this, host_t *host)
+{
+ this->packet->set_source(this->packet, host);
+}
+
+/**
+ * Implementation of message_t.set_destination.
+ */
+static void set_destination(private_message_t *this, host_t *host)
+{
+ this->packet->set_destination(this->packet, host);
+}
+
+/**
+ * Implementation of message_t.get_source.
+ */
+static host_t* get_source(private_message_t *this)
+{
+ return this->packet->get_source(this->packet);
+}
+
+/**
+ * Implementation of message_t.get_destination.
+ */
+static host_t * get_destination(private_message_t *this)
+{
+ return this->packet->get_destination(this->packet);
+}
+
+/**
+ * Implementation of message_t.create_payload_enumerator.
+ */
+static enumerator_t *create_payload_enumerator(private_message_t *this)
+{
+ return this->payloads->create_enumerator(this->payloads);
+}
+
+/**
+ * Implementation of message_t.get_payload.
+ */
+static payload_t *get_payload(private_message_t *this, payload_type_t type)
+{
+ payload_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_type(current) == type)
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Implementation of message_t.get_notify
+ */
+static notify_payload_t* get_notify(private_message_t *this, notify_type_t type)
+{
+ enumerator_t *enumerator;
+ notify_payload_t *notify = NULL;
+ payload_t *payload;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == type)
+ {
+ break;
+ }
+ notify = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return notify;
+}
+
+/**
+ * get a string representation of the message
+ */
+static char* get_string(private_message_t *this, char *buf, int len)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ int written;
+ char *pos = buf;
+
+ memset(buf, 0, len);
+ len--;
+
+ written = snprintf(pos, len, "%N %s %d [",
+ exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response",
+ this->message_id);
+ if (written >= len || written < 0)
+ {
+ return "";
+ }
+ pos += written;
+ len -= written;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ written = snprintf(pos, len, " %N", payload_type_short_names,
+ payload->get_type(payload));
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ written = snprintf(pos, len, "(%N)", notify_type_short_names,
+ notify->get_notify_type(notify));
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ }
+ if (payload->get_type(payload) == EXTENSIBLE_AUTHENTICATION)
+ {
+ eap_payload_t *eap = (eap_payload_t*)payload;
+ u_int32_t vendor;
+ eap_type_t type;
+ char method[64] = "";
+
+ type = eap->get_type(eap, &vendor);
+ if (type)
+ {
+ if (vendor)
+ {
+ snprintf(method, sizeof(method), "/%d-%d", type, vendor);
+ }
+ else
+ {
+ snprintf(method, sizeof(method), "/%N",
+ eap_type_short_names, type);
+ }
+ }
+ written = snprintf(pos, len, "/%N%s", eap_code_short_names,
+ eap->get_code(eap), method);
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* remove last space */
+ snprintf(pos, len, " ]");
+ return buf;
+}
+
+/**
+ * reorder payloads depending on reordering rules
+ */
+static void order_payloads(private_message_t *this)
+{
+ linked_list_t *list;
+ payload_t *payload;
+ int i;
+
+ /* move to temp list */
+ list = linked_list_create();
+ while (this->payloads->remove_last(this->payloads,
+ (void**)&payload) == SUCCESS)
+ {
+ list->insert_first(list, payload);
+ }
+ /* for each rule, ... */
+ for (i = 0; i < this->message_rule->payload_order_count; i++)
+ {
+ enumerator_t *enumerator;
+ notify_payload_t *notify;
+ payload_order_t order = this->message_rule->payload_order[i];
+
+ /* ... find all payload ... */
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ /* ... with that type ... */
+ if (payload->get_type(payload) == order.type)
+ {
+ notify = (notify_payload_t*)payload;
+
+ /**... and check notify for type. */
+ if (order.type != NOTIFY || order.notify == 0 ||
+ order.notify == notify->get_notify_type(notify))
+ {
+ list->remove_at(list, enumerator);
+ add_payload(this, payload);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ /* append all payloads without a rule to the end */
+ while (list->remove_last(list, (void**)&payload) == SUCCESS)
+ {
+ /* do not complain about payloads in private use space */
+ if (payload->get_type(payload) < 128)
+ {
+ DBG1(DBG_ENC, "payload %N has no ordering rule in %N %s",
+ payload_type_names, payload->get_type(payload),
+ exchange_type_names, this->message_rule->exchange_type,
+ this->message_rule->is_request ? "request" : "response");
+ }
+ add_payload(this, payload);
+ }
+ list->destroy(list);
+}
+
+/**
+ * Implementation of private_message_t.encrypt_payloads.
+ */
+static status_t encrypt_payloads(private_message_t *this,
+ crypter_t *crypter, signer_t* signer)
+{
+ encryption_payload_t *encryption;
+ linked_list_t *payloads;
+ payload_t *current;
+ status_t status;
+
+ if (!this->message_rule->encrypted_content)
+ {
+ DBG2(DBG_ENC, "message doesn't have to be encrypted");
+ /* message contains no content to encrypt */
+ return SUCCESS;
+ }
+
+ if (!crypter || !signer)
+ {
+ DBG2(DBG_ENC, "no crypter or signer specified, do not encrypt message");
+ /* message contains no content to encrypt */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_ENC, "copy all payloads to a temporary list");
+ payloads = linked_list_create();
+
+ /* first copy all payloads in a temporary list */
+ while (this->payloads->get_count(this->payloads) > 0)
+ {
+ this->payloads->remove_first(this->payloads, (void**)&current);
+ payloads->insert_last(payloads, current);
+ }
+
+ encryption = encryption_payload_create();
+
+ DBG2(DBG_ENC, "check each payloads if they have to get encrypted");
+ while (payloads->get_count(payloads) > 0)
+ {
+ payload_rule_t *rule;
+ payload_type_t type;
+ bool to_encrypt = TRUE;
+
+ payloads->remove_first(payloads, (void**)&current);
+
+ type = current->get_type(current);
+ if (get_payload_rule(this, type, &rule) == SUCCESS)
+ {
+ to_encrypt = rule->encrypted;
+ }
+ if (to_encrypt)
+ {
+ DBG2(DBG_ENC, "insert payload %N to encryption payload",
+ payload_type_names, current->get_type(current));
+ encryption->add_payload(encryption, current);
+ }
+ else
+ {
+ DBG2(DBG_ENC, "insert payload %N unencrypted",
+ payload_type_names, current->get_type(current));
+ add_payload(this, (payload_t*)current);
+ }
+ }
+
+ DBG2(DBG_ENC, "encrypting encryption payload");
+ encryption->set_transforms(encryption, crypter, signer);
+ status = encryption->encrypt(encryption);
+ DBG2(DBG_ENC, "add encrypted payload to payload list");
+ add_payload(this, (payload_t*)encryption);
+
+ payloads->destroy(payloads);
+
+ return status;
+}
+
+/**
+ * Implementation of message_t.generate.
+ */
+static status_t generate(private_message_t *this, crypter_t *crypter,
+ signer_t* signer, packet_t **packet)
+{
+ generator_t *generator;
+ ike_header_t *ike_header;
+ payload_t *payload, *next_payload;
+ enumerator_t *enumerator;
+ status_t status;
+ chunk_t packet_data;
+ char str[256];
+
+ if (is_encoded(this))
+ {
+ /* already generated, return a new packet clone */
+ *packet = this->packet->clone(this->packet);
+ return SUCCESS;
+ }
+
+ if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
+ {
+ DBG1(DBG_ENC, "exchange type is not defined");
+ return INVALID_STATE;
+ }
+
+ if (this->packet->get_source(this->packet) == NULL ||
+ this->packet->get_destination(this->packet) == NULL)
+ {
+ DBG1(DBG_ENC, "%s not defined",
+ !this->packet->get_source(this->packet) ? "source" : "destination");
+ return INVALID_STATE;
+ }
+
+ /* set the rules for this messge */
+ status = set_message_rule(this);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "no message rules specified for this message type");
+ return NOT_SUPPORTED;
+ }
+
+ order_payloads(this);
+
+ DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
+
+ /* going to encrypt all content which have to be encrypted */
+ status = encrypt_payloads(this, crypter, signer);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "payload encryption failed");
+ return status;
+ }
+
+ /* build ike header */
+ ike_header = ike_header_create();
+
+ ike_header->set_exchange_type(ike_header, this->exchange_type);
+ ike_header->set_message_id(ike_header, this->message_id);
+ ike_header->set_response_flag(ike_header, !this->is_request);
+ ike_header->set_initiator_flag(ike_header,
+ this->ike_sa_id->is_initiator(this->ike_sa_id));
+ ike_header->set_initiator_spi(ike_header,
+ this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
+ ike_header->set_responder_spi(ike_header,
+ this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+
+ generator = generator_create();
+
+ payload = (payload_t*)ike_header;
+
+ /* generate every payload expect last one, this is done later*/
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &next_payload))
+ {
+ payload->set_next_type(payload, next_payload->get_type(next_payload));
+ generator->generate_payload(generator, payload);
+ payload = next_payload;
+ }
+ enumerator->destroy(enumerator);
+
+ /* last payload has no next payload*/
+ payload->set_next_type(payload, NO_PAYLOAD);
+
+ generator->generate_payload(generator, payload);
+
+ ike_header->destroy(ike_header);
+
+ /* build packet */
+ generator->write_to_chunk(generator, &packet_data);
+ generator->destroy(generator);
+
+ /* if last payload is of type encrypted, integrity checksum if necessary */
+ if (payload->get_type(payload) == ENCRYPTED)
+ {
+ DBG2(DBG_ENC, "build signature on whole message");
+ encryption_payload_t *encryption_payload = (encryption_payload_t*)payload;
+ status = encryption_payload->build_signature(encryption_payload, packet_data);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ this->packet->set_data(this->packet, packet_data);
+
+ /* clone packet for caller */
+ *packet = this->packet->clone(this->packet);
+
+ DBG2(DBG_ENC, "message generated successfully");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.get_packet.
+ */
+static packet_t *get_packet(private_message_t *this)
+{
+ if (this->packet == NULL)
+ {
+ return NULL;
+ }
+ return this->packet->clone(this->packet);
+}
+
+/**
+ * Implementation of message_t.get_packet_data.
+ */
+static chunk_t get_packet_data(private_message_t *this)
+{
+ if (this->packet == NULL)
+ {
+ return chunk_empty;
+ }
+ return chunk_clone(this->packet->get_data(this->packet));
+}
+
+/**
+ * Implementation of message_t.parse_header.
+ */
+static status_t parse_header(private_message_t *this)
+{
+ ike_header_t *ike_header;
+ status_t status;
+
+ DBG2(DBG_ENC, "parsing header of message");
+
+ this->parser->reset_context(this->parser);
+ status = this->parser->parse_payload(this->parser, HEADER,
+ (payload_t**)&ike_header);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "header could not be parsed");
+ return status;
+
+ }
+
+ /* verify payload */
+ status = ike_header->payload_interface.verify(
+ &ike_header->payload_interface);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "header verification failed");
+ ike_header->destroy(ike_header);
+ return status;
+ }
+
+ if (this->ike_sa_id != NULL)
+ {
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ }
+
+ this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header),
+ ike_header->get_responder_spi(ike_header),
+ ike_header->get_initiator_flag(ike_header));
+
+ this->exchange_type = ike_header->get_exchange_type(ike_header);
+ this->message_id = ike_header->get_message_id(ike_header);
+ this->is_request = (!(ike_header->get_response_flag(ike_header)));
+ this->major_version = ike_header->get_maj_version(ike_header);
+ this->minor_version = ike_header->get_min_version(ike_header);
+ this->first_payload = ike_header->payload_interface.get_next_type(
+ &ike_header->payload_interface);
+
+ DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response");
+
+ ike_header->destroy(ike_header);
+
+ /* get the rules for this messge */
+ status = set_message_rule(this);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "no message rules specified for a %N %s",
+ exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response");
+ }
+
+ return status;
+}
+
+/**
+ * Implementation of private_message_t.decrypt_and_verify_payloads.
+ */
+static status_t decrypt_payloads(private_message_t *this, crypter_t *crypter,
+ signer_t* signer)
+{
+ bool current_payload_was_encrypted = FALSE;
+ payload_t *previous_payload = NULL;
+ int payload_number = 1;
+ iterator_t *iterator;
+ payload_t *current_payload;
+ status_t status;
+
+ iterator = this->payloads->create_iterator(this->payloads,TRUE);
+
+ /* process each payload and decrypt a encryption payload */
+ while(iterator->iterate(iterator, (void**)&current_payload))
+ {
+ payload_rule_t *payload_rule;
+ payload_type_t current_payload_type;
+
+ /* needed to check */
+ current_payload_type = current_payload->get_type(current_payload);
+
+ DBG2(DBG_ENC, "process payload of type %N",
+ payload_type_names, current_payload_type);
+
+ if (current_payload_type == ENCRYPTED)
+ {
+ encryption_payload_t *encryption_payload;
+ payload_t *current_encrypted_payload;
+
+ encryption_payload = (encryption_payload_t*)current_payload;
+
+ DBG2(DBG_ENC, "found an encryption payload");
+
+ if (payload_number != this->payloads->get_count(this->payloads))
+ {
+ /* encrypted payload is not last one */
+ DBG1(DBG_ENC, "encrypted payload is not last payload");
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+ /* decrypt */
+ encryption_payload->set_transforms(encryption_payload,
+ crypter, signer);
+ DBG2(DBG_ENC, "verify signature of encryption payload");
+ status = encryption_payload->verify_signature(encryption_payload,
+ this->packet->get_data(this->packet));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "encryption payload signature invalid");
+ iterator->destroy(iterator);
+ return FAILED;
+ }
+ DBG2(DBG_ENC, "decrypting content of encryption payload");
+ status = encryption_payload->decrypt(encryption_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "encrypted payload could not be decrypted and parsed");
+ iterator->destroy(iterator);
+ return PARSE_ERROR;
+ }
+
+ /* needed later to find out if a payload was encrypted */
+ current_payload_was_encrypted = TRUE;
+
+ /* check if there are payloads contained in the encryption payload */
+ if (encryption_payload->get_payload_count(encryption_payload) == 0)
+ {
+ DBG2(DBG_ENC, "encrypted payload is empty");
+ /* remove the encryption payload, is not needed anymore */
+ iterator->remove(iterator);
+ /* encrypted payload contains no other payload */
+ current_payload_type = NO_PAYLOAD;
+ }
+ else
+ {
+ /* encryption_payload is replaced with first payload contained
+ * in encryption_payload */
+ encryption_payload->remove_first_payload(encryption_payload,
+ &current_encrypted_payload);
+ iterator->replace(iterator, NULL,
+ (void *)current_encrypted_payload);
+ current_payload_type = current_encrypted_payload->get_type(
+ current_encrypted_payload);
+ }
+
+ /* is the current paylad the first in the message? */
+ if (previous_payload == NULL)
+ {
+ /* yes, set the first payload type of the message to the
+ * current type */
+ this->first_payload = current_payload_type;
+ }
+ else
+ {
+ /* no, set the next_type of the previous payload to the
+ * current type */
+ previous_payload->set_next_type(previous_payload,
+ current_payload_type);
+ }
+
+ /* all encrypted payloads are added to the payload list */
+ while (encryption_payload->get_payload_count(encryption_payload) > 0)
+ {
+ encryption_payload->remove_first_payload(encryption_payload,
+ &current_encrypted_payload);
+ DBG2(DBG_ENC, "insert unencrypted payload of type "
+ "%N at end of list", payload_type_names,
+ current_encrypted_payload->get_type(
+ current_encrypted_payload));
+ this->payloads->insert_last(this->payloads,
+ current_encrypted_payload);
+ }
+
+ /* encryption payload is processed, payloads are moved. Destroy it. */
+ encryption_payload->destroy(encryption_payload);
+ }
+
+ /* we allow unknown payloads of any type and don't bother if it was
+ * encrypted. Not our problem. */
+ if (current_payload_type != UNKNOWN_PAYLOAD &&
+ current_payload_type != NO_PAYLOAD)
+ {
+ /* get the ruleset for found payload */
+ status = get_payload_rule(this, current_payload_type, &payload_rule);
+ if (status != SUCCESS)
+ {
+ /* payload is not allowed */
+ DBG1(DBG_ENC, "payload type %N not allowed",
+ payload_type_names, current_payload_type);
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+
+ /* check if the payload was encrypted, and if it should been have
+ * encrypted */
+ if (payload_rule->encrypted != current_payload_was_encrypted)
+ {
+ /* payload was not encrypted, but should have been.
+ * or vice-versa */
+ DBG1(DBG_ENC, "payload type %N should be %s!",
+ payload_type_names, current_payload_type,
+ (payload_rule->encrypted) ? "encrypted" : "not encrypted");
+ iterator->destroy(iterator);
+ return VERIFY_ERROR;
+ }
+ }
+ /* advance to the next payload */
+ payload_number++;
+ /* is stored to set next payload in case of found encryption payload */
+ previous_payload = current_payload;
+ }
+ iterator->destroy(iterator);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of private_message_t.verify.
+ */
+static status_t verify(private_message_t *this)
+{
+ int i;
+ enumerator_t *enumerator;
+ payload_t *current_payload;
+ size_t total_found_payloads = 0;
+
+ DBG2(DBG_ENC, "verifying message structure");
+
+ /* check for payloads with wrong count*/
+ for (i = 0; i < this->message_rule->payload_rule_count; i++)
+ {
+ size_t found_payloads = 0;
+ payload_rule_t *rule;
+
+ rule = &this->message_rule->payload_rules[i];
+ enumerator = create_payload_enumerator(this);
+
+ /* check all payloads for specific rule */
+ while (enumerator->enumerate(enumerator, &current_payload))
+ {
+ payload_type_t current_payload_type;
+ unknown_payload_t *unknown_payload;
+
+ current_payload_type = current_payload->get_type(current_payload);
+ if (current_payload_type == UNKNOWN_PAYLOAD)
+ {
+ /* unknown payloads are ignored, IF they are not critical */
+ unknown_payload = (unknown_payload_t*)current_payload;
+ if (unknown_payload->is_critical(unknown_payload))
+ {
+ DBG1(DBG_ENC, "%N is not supported, but its critical!",
+ payload_type_names, current_payload_type);
+ enumerator->destroy(enumerator);
+ return NOT_SUPPORTED;
+ }
+ }
+ else if (current_payload_type == rule->payload_type)
+ {
+ found_payloads++;
+ total_found_payloads++;
+ DBG2(DBG_ENC, "found payload of type %N", payload_type_names,
+ rule->payload_type);
+
+ /* as soon as ohe payload occures more then specified,
+ * the verification fails */
+ if (found_payloads >
+ rule->max_occurence)
+ {
+ DBG1(DBG_ENC, "payload of type %N more than %d times (%d) "
+ "occured in current message", payload_type_names,
+ current_payload_type, rule->max_occurence,
+ found_payloads);
+ enumerator->destroy(enumerator);
+ return VERIFY_ERROR;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (found_payloads < rule->min_occurence)
+ {
+ DBG1(DBG_ENC, "payload of type %N not occured %d times (%d)",
+ payload_type_names, rule->payload_type, rule->min_occurence,
+ found_payloads);
+ return VERIFY_ERROR;
+ }
+ if (rule->sufficient)
+ {
+ return SUCCESS;
+ }
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.parse_body.
+ */
+static status_t parse_body(private_message_t *this, crypter_t *crypter,
+ signer_t *signer)
+{
+ status_t status = SUCCESS;
+ payload_type_t current_payload_type;
+ char str[256];
+
+ current_payload_type = this->first_payload;
+
+ DBG2(DBG_ENC, "parsing body of message, first payload is %N",
+ payload_type_names, current_payload_type);
+
+ /* parse payload for payload, while there are more available */
+ while ((current_payload_type != NO_PAYLOAD))
+ {
+ payload_t *current_payload;
+
+ DBG2(DBG_ENC, "starting parsing a %N payload",
+ payload_type_names, current_payload_type);
+
+ /* parse current payload */
+ status = this->parser->parse_payload(this->parser, current_payload_type,
+ (payload_t**)&current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "payload type %N could not be parsed",
+ payload_type_names, current_payload_type);
+ return PARSE_ERROR;
+ }
+
+ DBG2(DBG_ENC, "verifying payload of type %N",
+ payload_type_names, current_payload_type);
+
+ /* verify it, stop parsig if its invalid */
+ status = current_payload->verify(current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N payload verification failed",
+ payload_type_names, current_payload_type);
+ current_payload->destroy(current_payload);
+ return VERIFY_ERROR;
+ }
+
+ DBG2(DBG_ENC, "%N payload verified. Adding to payload list",
+ payload_type_names, current_payload_type);
+ this->payloads->insert_last(this->payloads,current_payload);
+
+ /* an encryption payload is the last one, so STOP here. decryption is
+ * done later */
+ if (current_payload_type == ENCRYPTED)
+ {
+ DBG2(DBG_ENC, "%N payload found. Stop parsing",
+ payload_type_names, current_payload_type);
+ break;
+ }
+
+ /* get next payload type */
+ current_payload_type = current_payload->get_next_type(current_payload);
+ }
+
+ if (current_payload_type == ENCRYPTED)
+ {
+ status = decrypt_payloads(this,crypter,signer);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "could not decrypt payloads");
+ return status;
+ }
+ }
+
+ status = verify(this);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of message_t.destroy.
+ */
+static void destroy (private_message_t *this)
+{
+ DESTROY_IF(this->ike_sa_id);
+ this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
+ this->packet->destroy(this->packet);
+ this->parser->destroy(this->parser);
+ free(this);
+}
+
+/*
+ * Described in Header-File
+ */
+message_t *message_create_from_packet(packet_t *packet)
+{
+ private_message_t *this = malloc_thing(private_message_t);
+
+ /* public functions */
+ this->public.set_major_version = (void(*)(message_t*, u_int8_t))set_major_version;
+ this->public.get_major_version = (u_int8_t(*)(message_t*))get_major_version;
+ this->public.set_minor_version = (void(*)(message_t*, u_int8_t))set_minor_version;
+ this->public.get_minor_version = (u_int8_t(*)(message_t*))get_minor_version;
+ this->public.set_message_id = (void(*)(message_t*, u_int32_t))set_message_id;
+ this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id;
+ this->public.get_initiator_spi = (u_int64_t(*)(message_t*))get_initiator_spi;
+ this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi;
+ this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id;
+ this->public.get_ike_sa_id = (ike_sa_id_t*(*)(message_t*))get_ike_sa_id;
+ this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type;
+ this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type;
+ this->public.get_first_payload_type = (payload_type_t(*)(message_t*))get_first_payload_type;
+ this->public.set_request = (void(*)(message_t*, bool))set_request;
+ this->public.get_request = (bool(*)(message_t*))get_request;
+ this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload;
+ this->public.add_notify = (void(*)(message_t*,bool,notify_type_t,chunk_t))add_notify;
+ this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate;
+ this->public.set_source = (void (*) (message_t*,host_t*)) set_source;
+ this->public.get_source = (host_t * (*) (message_t*)) get_source;
+ this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination;
+ this->public.get_destination = (host_t * (*) (message_t*)) get_destination;
+ this->public.create_payload_enumerator = (enumerator_t * (*) (message_t *)) create_payload_enumerator;
+ this->public.get_payload = (payload_t * (*) (message_t *, payload_type_t)) get_payload;
+ this->public.get_notify = (notify_payload_t*(*)(message_t*, notify_type_t type))get_notify;
+ this->public.parse_header = (status_t (*) (message_t *)) parse_header;
+ this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body;
+ this->public.get_packet = (packet_t * (*) (message_t*)) get_packet;
+ this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data;
+ this->public.destroy = (void(*)(message_t*))destroy;
+
+ /* private values */
+ this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
+ this->is_request = TRUE;
+ this->ike_sa_id = NULL;
+ this->first_payload = NO_PAYLOAD;
+ this->message_id = 0;
+
+ /* private values */
+ if (packet == NULL)
+ {
+ packet = packet_create();
+ }
+ this->message_rule = NULL;
+ this->packet = packet;
+ this->payloads = linked_list_create();
+
+ /* parser is created from data of packet */
+ this->parser = parser_create(this->packet->get_data(this->packet));
+
+ return (&this->public);
+}
+
+/*
+ * Described in Header.
+ */
+message_t *message_create()
+{
+ return message_create_from_packet(NULL);
+}
+
diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h
new file mode 100644
index 000000000..2c7718f49
--- /dev/null
+++ b/src/libcharon/encoding/message.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup message message
+ * @{ @ingroup encoding
+ */
+
+#ifndef MESSAGE_H_
+#define MESSAGE_H_
+
+typedef struct message_t message_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <network/packet.h>
+#include <encoding/payloads/ike_header.h>
+#include <encoding/payloads/notify_payload.h>
+#include <utils/linked_list.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * This class is used to represent an IKEv2-Message.
+ *
+ * The message handles parsing and generation of payloads
+ * via parser_t/generator_t. Encryption is done transparently
+ * via the encryption_payload_t. A set of rules for messages
+ * and payloads does check parsed messages.
+ */
+struct message_t {
+
+ /**
+ * Sets the IKE major version of the message.
+ *
+ * @param major_version major version to set
+ */
+ void (*set_major_version) (message_t *this,u_int8_t major_version);
+
+ /**
+ * Gets the IKE major version of the message.
+ *
+ * @return major version of the message
+ */
+ u_int8_t (*get_major_version) (message_t *this);
+
+ /**
+ * Sets the IKE minor version of the message.
+ *
+ * @param minor_version minor version to set
+ */
+ void (*set_minor_version) (message_t *this,u_int8_t minor_version);
+
+ /**
+ * Gets the IKE minor version of the message.
+ *
+ * @return minor version of the message
+ */
+ u_int8_t (*get_minor_version) (message_t *this);
+
+ /**
+ * Sets the Message ID of the message.
+ *
+ * @param message_id message_id to set
+ */
+ void (*set_message_id) (message_t *this,u_int32_t message_id);
+
+ /**
+ * Gets the Message ID of the message.
+ *
+ * @return message_id type of the message
+ */
+ u_int32_t (*get_message_id) (message_t *this);
+
+ /**
+ * Gets the initiator SPI of the message.
+ *
+ * @return initiator spi of the message
+ */
+ u_int64_t (*get_initiator_spi) (message_t *this);
+
+ /**
+ * Gets the responder SPI of the message.
+ *
+ * @return responder spi of the message
+ */
+ u_int64_t (*get_responder_spi) (message_t *this);
+
+ /**
+ * Sets the IKE_SA ID of the message.
+ *
+ * ike_sa_id gets cloned.
+ *
+ * @param ike_sa_id ike_sa_id to set
+ */
+ void (*set_ike_sa_id) (message_t *this, ike_sa_id_t * ike_sa_id);
+
+ /**
+ * Gets the IKE_SA ID of the message.
+ *
+ * The ike_sa_id points to the message internal id, do not modify.
+ *
+ * @return ike_sa_id of message
+ */
+ ike_sa_id_t *(*get_ike_sa_id) (message_t *this);
+
+ /**
+ * Sets the exchange type of the message.
+ *
+ * @param exchange_type exchange_type to set
+ */
+ void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type);
+
+ /**
+ * Gets the exchange type of the message.
+ *
+ * @return exchange type of the message
+ */
+ exchange_type_t (*get_exchange_type) (message_t *this);
+
+ /**
+ * Gets the payload type of the first payload.
+ *
+ * @return payload type of the first payload
+ */
+ payload_type_t (*get_first_payload_type) (message_t *this);
+
+ /**
+ * Sets the request flag.
+ *
+ * @param request TRUE if message is a request, FALSE if it is a reply
+ */
+ void (*set_request) (message_t *this, bool request);
+
+ /**
+ * Gets request flag.
+ *
+ * @return TRUE if message is a request, FALSE if it is a reply
+ */
+ bool (*get_request) (message_t *this);
+
+ /**
+ * Append a payload to the message.
+ *
+ * If the payload must be encrypted is not specified here. Encryption
+ * of payloads is evaluated via internal rules for the messages and
+ * is done before generation. The order of payloads may change, since
+ * all payloads to encrypt are added to the encryption payload, which is
+ * always the last one.
+ *
+ * @param payload payload to append
+ */
+ void (*add_payload) (message_t *this, payload_t *payload);
+
+ /**
+ * Build a notify payload and add it to the message.
+ *
+ * This is a helper method to create notify messages or add
+ * notify payload to messages. The flush parameter specifies if existing
+ * payloads should get removed before appending the notify.
+ *
+ * @param flush TRUE to remove existing payloads
+ * @param type type of the notify
+ * @param data a chunk of data to add to the notify, gets cloned
+ */
+ void (*add_notify) (message_t *this, bool flush, notify_type_t type,
+ chunk_t data);
+
+ /**
+ * Parses header of message.
+ *
+ * Begins parisng of a message created via message_create_from_packet().
+ * The parsing context is stored, so a subsequent call to parse_body()
+ * will continue the parsing process.
+ *
+ * @return
+ * - SUCCESS if header could be parsed
+ * - PARSE_ERROR if corrupted/invalid data found
+ * - FAILED if consistence check of header failed
+ */
+ status_t (*parse_header) (message_t *this);
+
+ /**
+ * Parses body of message.
+ *
+ * The body gets not only parsed, but rather it gets verified.
+ * All payloads are verified if they are allowed to exist in the message
+ * of this type and if their own structure is ok.
+ * If there are encrypted payloads, they get decrypted via the supplied
+ * crypter. Also the message integrity gets verified with the supplied
+ * signer.
+ * Crypter/signer can be omitted (by passing NULL) when no encryption
+ * payload is expected.
+ *
+ * @param crypter crypter to decrypt encryption payloads
+ * @param signer signer to verifiy a message with an encryption payload
+ * @return
+ * - SUCCESS if parsing successful
+ * - NOT_SUPPORTED if ciritcal unknown payloads found
+ * - NOT_SUPPORTED if message type is not supported!
+ * - PARSE_ERROR if message parsing failed
+ * - VERIFY_ERROR if message verification failed (bad syntax)
+ * - FAILED if integrity check failed
+ * - INVALID_STATE if crypter/signer not supplied, but needed
+ */
+ status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer);
+
+ /**
+ * Generates the UDP packet of specific message.
+ *
+ * Payloads which must be encrypted are generated first and added to
+ * an encryption payload. This encryption payload will get encrypted via
+ * the supplied crypter. Then all other payloads and the header get generated.
+ * After that, the checksum is added to the encryption payload over the full
+ * message.
+ * Crypter/signer can be omitted (by passing NULL) when no encryption
+ * payload is expected.
+ * Generation is only done once, multiple calls will just return a packet copy.
+ *
+ * @param crypter crypter to use when a payload must be encrypted
+ * @param signer signer to build a mac
+ * @param packet copy of generated packet
+ * @return
+ * - SUCCESS if packet could be generated
+ * - INVALID_STATE if exchange type is currently not set
+ * - NOT_FOUND if no rules found for message generation
+ * - INVALID_STATE if crypter/signer not supplied but needed.
+ */
+ status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet);
+
+ /**
+ * Gets the source host informations.
+ *
+ * @warning Returned host_t object is not getting cloned,
+ * do not destroy nor modify.
+ *
+ * @return host_t object representing source host
+ */
+ host_t * (*get_source) (message_t *this);
+
+ /**
+ * Sets the source host informations.
+ *
+ * @warning host_t object is not getting cloned and gets destroyed by
+ * message_t.destroy or next call of message_t.set_source.
+ *
+ * @param host host_t object representing source host
+ */
+ void (*set_source) (message_t *this, host_t *host);
+
+ /**
+ * Gets the destination host informations.
+ *
+ * @warning Returned host_t object is not getting cloned,
+ * do not destroy nor modify.
+ *
+ * @return host_t object representing destination host
+ */
+ host_t * (*get_destination) (message_t *this);
+
+ /**
+ * Sets the destination host informations.
+ *
+ * @warning host_t object is not getting cloned and gets destroyed by
+ * message_t.destroy or next call of message_t.set_destination.
+ *
+ * @param host host_t object representing destination host
+ */
+ void (*set_destination) (message_t *this, host_t *host);
+
+ /**
+ * Create an enumerator over all payloads.
+ *
+ * @return enumerator over payload_t
+ */
+ enumerator_t * (*create_payload_enumerator) (message_t *this);
+
+ /**
+ * Find a payload of a specific type.
+ *
+ * Returns the first occurance.
+ *
+ * @param type type of the payload to find
+ * @return payload, or NULL if no such payload found
+ */
+ payload_t* (*get_payload) (message_t *this, payload_type_t type);
+
+ /**
+ * Get the first notify payload of a specific type.
+ *
+ * @param type type of notification payload
+ * @return notify payload, NULL if no such notify found
+ */
+ notify_payload_t* (*get_notify)(message_t *this, notify_type_t type);
+
+ /**
+ * Returns a clone of the internal stored packet_t object.
+ *
+ * @return packet_t object as clone of internal one
+ */
+ packet_t * (*get_packet) (message_t *this);
+
+ /**
+ * Returns a clone of the internal stored packet_t data.
+ *
+ * @return clone of the internal stored packet_t data.
+ */
+ chunk_t (*get_packet_data) (message_t *this);
+
+ /**
+ * Destroys a message and all including objects.
+ */
+ void (*destroy) (message_t *this);
+};
+
+/**
+ * Creates an message_t object from a incoming UDP Packet.
+ *
+ * @warning the given packet_t object is not copied and gets
+ * destroyed in message_t's destroy call.
+ *
+ * - exchange_type is set to NOT_SET
+ * - original_initiator is set to TRUE
+ * - is_request is set to TRUE
+ * Call message_t.parse_header afterwards.
+ *
+ * @param packet packet_t object which is assigned to message
+ * @return message_t object
+ */
+message_t * message_create_from_packet(packet_t *packet);
+
+
+/**
+ * Creates an empty message_t object.
+ *
+ * - exchange_type is set to NOT_SET
+ * - original_initiator is set to TRUE
+ * - is_request is set to TRUE
+ *
+ * @return message_t object
+ */
+message_t * message_create(void);
+
+#endif /** MESSAGE_H_ @}*/
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
new file mode 100644
index 000000000..9aa34b1bc
--- /dev/null
+++ b/src/libcharon/encoding/parser.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "parser.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <encoding/payloads/transform_attribute.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+
+
+typedef struct private_parser_t private_parser_t;
+
+/**
+ * Private data stored in a context.
+ *
+ * Contains pointers and counters to store current state.
+ */
+struct private_parser_t {
+ /**
+ * Public members, see parser_t.
+ */
+ parser_t public;
+
+ /**
+ * Current bit for reading in input data.
+ */
+ u_int8_t bit_pos;
+
+ /**
+ * Current byte for reading in input data.
+ */
+ u_int8_t *byte_pos;
+
+ /**
+ * Input data to parse.
+ */
+ u_int8_t *input;
+
+ /**
+ * Roof of input, used for length-checking.
+ */
+ u_int8_t *input_roof;
+
+ /**
+ * Set of encoding rules for this parsing session.
+ */
+ encoding_rule_t *rules;
+};
+
+/**
+ * Forward declaration
+ */
+static status_t parse_payload(private_parser_t *this,
+ payload_type_t payload_type, payload_t **payload);
+
+/**
+ * Log invalid length error
+ */
+static bool short_input(private_parser_t *this, int number)
+{
+ DBG1(DBG_ENC, " not enough input to parse rule %d %N",
+ number, encoding_type_names, this->rules[number].type);
+ return FALSE;
+}
+
+/**
+ * Log unaligned rules
+ */
+static bool bad_bitpos(private_parser_t *this, int number)
+{
+ DBG1(DBG_ENC, " found rule %d %N on bitpos %d",
+ number, encoding_type_names, this->rules[number].type, this->bit_pos);
+ return FALSE;
+}
+
+/**
+ * Parse a 4-Bit unsigned integer from the current parsing position.
+ */
+static bool parse_uint4(private_parser_t *this, int rule_number,
+ u_int8_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ switch (this->bit_pos)
+ {
+ case 0:
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos) >> 4;
+ }
+ this->bit_pos = 4;
+ break;
+ case 4:
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos) & 0x0F;
+ }
+ this->bit_pos = 0;
+ this->byte_pos++;
+ break;
+ default:
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a 8-Bit unsigned integer from the current parsing position.
+ */
+static bool parse_uint8(private_parser_t *this, int rule_number,
+ u_int8_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ *output_pos = *(this->byte_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos++;
+ return TRUE;
+}
+
+/**
+ * Parse a 15-Bit unsigned integer from the current parsing position.
+ */
+static bool parse_uint15(private_parser_t *this, int rule_number,
+ u_int16_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos != 1)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+ *output_pos = ntohs(*output_pos) & ~0x8000;
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int16_t);
+ this->bit_pos = 0;
+ return TRUE;
+}
+
+/**
+ * Parse a 16-Bit unsigned integer from the current parsing position.
+ */
+static bool parse_uint16(private_parser_t *this, int rule_number,
+ u_int16_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
+ *output_pos = ntohs(*output_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int16_t);
+ return TRUE;
+}
+/**
+ * Parse a 32-Bit unsigned integer from the current parsing position.
+ */
+static bool parse_uint32(private_parser_t *this, int rule_number,
+ u_int32_t *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
+ *output_pos = ntohl(*output_pos);
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->byte_pos += sizeof(u_int32_t);
+ return TRUE;
+}
+
+/**
+ * Parse a given amount of bytes and writes them to a specific location
+ */
+static bool parse_bytes(private_parser_t *this, int rule_number,
+ u_int8_t *output_pos, int bytes)
+{
+ if (this->byte_pos + bytes > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ memcpy(output_pos, this->byte_pos, bytes);
+ DBG3(DBG_ENC, " => %b", output_pos, bytes);
+ }
+ this->byte_pos += bytes;
+ return TRUE;
+}
+
+/**
+ * Parse a single Bit from the current parsing position
+ */
+static bool parse_bit(private_parser_t *this, int rule_number,
+ bool *output_pos)
+{
+ if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (output_pos)
+ {
+ u_int8_t mask;
+ mask = 0x01 << (7 - this->bit_pos);
+ *output_pos = *this->byte_pos & mask;
+
+ if (*output_pos)
+ { /* set to a "clean", comparable true */
+ *output_pos = TRUE;
+ }
+ DBG3(DBG_ENC, " => %d", *output_pos);
+ }
+ this->bit_pos = (this->bit_pos + 1) % 8;
+ if (this->bit_pos == 0)
+ {
+ this->byte_pos++;
+ }
+ return TRUE;
+}
+
+/**
+ * Parse substructures in a list.
+ */
+static bool parse_list(private_parser_t *this, int rule_number,
+ linked_list_t **output_pos, payload_type_t payload_type, int length)
+{
+ linked_list_t *list = *output_pos;
+
+ if (length < 0)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ while (length > 0)
+ {
+ u_int8_t *pos_before = this->byte_pos;
+ payload_t *payload;
+
+ DBG2(DBG_ENC, " %d bytes left, parsing recursively %N",
+ length, payload_type_names, payload_type);
+
+ if (parse_payload(this, payload_type, &payload) != SUCCESS)
+ {
+ DBG1(DBG_ENC, " parsing of a %N substructure failed",
+ payload_type_names, payload_type);
+ return FALSE;
+ }
+ list->insert_last(list, payload);
+ length -= this->byte_pos - pos_before;
+ }
+ if (length != 0)
+ { /* must yield exactly to zero */
+ DBG1(DBG_ENC, " length of %N substructure list invalid",
+ payload_type_names, payload_type);
+ return FALSE;
+ }
+ *output_pos = list;
+ return TRUE;
+}
+
+/**
+ * Parse data from current parsing position in a chunk.
+ */
+static bool parse_chunk(private_parser_t *this, int rule_number,
+ chunk_t *output_pos, int length)
+{
+ if (this->byte_pos + length > this->input_roof)
+ {
+ return short_input(this, rule_number);
+ }
+ if (this->bit_pos)
+ {
+ return bad_bitpos(this, rule_number);
+ }
+ if (output_pos)
+ {
+ *output_pos = chunk_alloc(length);
+ memcpy(output_pos->ptr, this->byte_pos, length);
+ DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
+ }
+ this->byte_pos += length;
+ return TRUE;
+}
+
+/**
+ * Implementation of parser_t.parse_payload.
+ */
+static status_t parse_payload(private_parser_t *this,
+ payload_type_t payload_type, payload_t **payload)
+{
+ payload_t *pld;
+ void *output;
+ size_t rule_count;
+ int payload_length = 0, spi_size = 0, attribute_length = 0;
+ u_int16_t ts_type = 0;
+ bool attribute_format = FALSE;
+ int rule_number;
+ encoding_rule_t *rule;
+
+ /* create instance of the payload to parse */
+ pld = payload_create(payload_type);
+
+ DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
+ payload_type_names, payload_type, this->input_roof - this->byte_pos);
+
+ DBG3(DBG_ENC, "parsing payload from %b",
+ this->byte_pos, this->input_roof - this->byte_pos);
+
+ if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
+ {
+ DBG1(DBG_ENC, " payload type %d is unknown, handling as %N",
+ payload_type, payload_type_names, UNKNOWN_PAYLOAD);
+ }
+
+ /* base pointer for output, avoids casting in every rule */
+ output = pld;
+
+ /* parse the payload with its own rulse */
+ pld->get_encoding_rules(pld, &this->rules, &rule_count);
+ for (rule_number = 0; rule_number < rule_count; rule_number++)
+ {
+ rule = &(this->rules[rule_number]);
+ DBG2(DBG_ENC, " parsing rule %d %N",
+ rule_number, encoding_type_names, rule->type);
+ switch (rule->type)
+ {
+ case U_INT_4:
+ {
+ if (!parse_uint4(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_8:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_16:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case U_INT_32:
+ {
+ if (!parse_uint32(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case IKE_SPI:
+ {
+ if (!parse_bytes(this, rule_number, output + rule->offset, 8))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BIT:
+ {
+ if (!parse_bit(this, rule_number, NULL))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case RESERVED_BYTE:
+ {
+ if (!parse_uint8(this, rule_number, NULL))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case FLAG:
+ {
+ if (!parse_bit(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PAYLOAD_LENGTH:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ /* parsed u_int16 should be aligned */
+ payload_length = *(u_int16_t*)(output + rule->offset);
+ if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case HEADER_LENGTH:
+ {
+ if (!parse_uint32(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case SPI_SIZE:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ spi_size = *(u_int8_t*)(output + rule->offset);
+ break;
+ }
+ case SPI:
+ {
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ spi_size))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case PROPOSALS:
+ {
+ if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ PROPOSAL_SUBSTRUCTURE,
+ payload_length - SA_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORMS:
+ {
+ if (payload_length <
+ spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRANSFORM_ATTRIBUTES:
+ {
+ if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRANSFORM_ATTRIBUTE,
+ payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTES:
+ {
+ if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ CONFIGURATION_ATTRIBUTE,
+ payload_length - CP_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ATTRIBUTE_FORMAT:
+ {
+ if (!parse_bit(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_format = *(bool*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_TYPE:
+ {
+ if (!parse_uint15(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTE_LENGTH:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_LENGTH_OR_VALUE:
+ {
+ if (!parse_uint16(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ attribute_length = *(u_int16_t*)(output + rule->offset);
+ break;
+ }
+ case ATTRIBUTE_VALUE:
+ {
+ if (attribute_format == FALSE &&
+ !parse_chunk(this, rule_number, output + rule->offset,
+ attribute_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case NONCE_DATA:
+ {
+ if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ID_DATA:
+ {
+ if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - ID_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case AUTH_DATA:
+ {
+ if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CERT_DATA:
+ {
+ if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - CERT_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CERTREQ_DATA:
+ {
+ if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case EAP_DATA:
+ {
+ if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - EAP_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case SPIS:
+ {
+ if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case VID_DATA:
+ {
+ if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case CONFIGURATION_ATTRIBUTE_VALUE:
+ {
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ attribute_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case KEY_EXCHANGE_DATA:
+ {
+ if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - KE_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case NOTIFICATION_DATA:
+ {
+ if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case ENCRYPTED_DATA:
+ {
+ if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TS_TYPE:
+ {
+ if (!parse_uint8(this, rule_number, output + rule->offset))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ ts_type = *(u_int8_t*)(output + rule->offset);
+ break;
+ }
+ case ADDRESS:
+ {
+ int address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ address_length))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case TRAFFIC_SELECTORS:
+ {
+ if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
+ !parse_list(this, rule_number, output + rule->offset,
+ TRAFFIC_SELECTOR_SUBSTRUCTURE,
+ payload_length - TS_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ case UNKNOWN_DATA:
+ {
+ if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
+ {
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ break;
+ }
+ default:
+ {
+ DBG1(DBG_ENC, " no rule to parse rule %d %N",
+ rule_number, encoding_type_names, rule->type);
+ pld->destroy(pld);
+ return PARSE_ERROR;
+ }
+ }
+ /* process next rulue */
+ rule++;
+ }
+
+ *payload = pld;
+ DBG2(DBG_ENC, "parsing %N payload finished",
+ payload_type_names, payload_type);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of parser_t.get_remaining_byte_count.
+ */
+static int get_remaining_byte_count (private_parser_t *this)
+{
+ return this->input_roof - this->byte_pos;
+}
+
+/**
+ * Implementation of parser_t.reset_context.
+ */
+static void reset_context (private_parser_t *this)
+{
+ this->byte_pos = this->input;
+ this->bit_pos = 0;
+}
+
+/**
+ * Implementation of parser_t.destroy.
+ */
+static void destroy(private_parser_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+parser_t *parser_create(chunk_t data)
+{
+ private_parser_t *this = malloc_thing(private_parser_t);
+
+ this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**))parse_payload;
+ this->public.reset_context = (void(*)(parser_t*)) reset_context;
+ this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count;
+ this->public.destroy = (void(*)(parser_t*)) destroy;
+
+ this->input = data.ptr;
+ this->byte_pos = data.ptr;
+ this->bit_pos = 0;
+ this->input_roof = data.ptr + data.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/parser.h b/src/libcharon/encoding/parser.h
new file mode 100644
index 000000000..27c5f03fe
--- /dev/null
+++ b/src/libcharon/encoding/parser.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup parser parser
+ * @{ @ingroup encoding
+ */
+
+#ifndef PARSER_H_
+#define PARSER_H_
+
+typedef struct parser_t parser_t;
+
+#include <library.h>
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * A parser_t class to parse IKEv2 payloads.
+ *
+ * A parser is used for parsing one chunk of data. Multiple
+ * payloads can be parsed out of the chunk using parse_payload.
+ * The parser remains the state until destroyed.
+ */
+struct parser_t {
+
+ /**
+ * Parses the next payload.
+ *
+ * @warning Caller is responsible for freeing allocated payload.
+ *
+ * Rules for parsing are described in the payload definition.
+ *
+ * @param payload_type payload type to parse
+ * @param payload pointer where parsed payload was allocated
+ * @return
+ * - SUCCESSFUL if succeeded,
+ * - PARSE_ERROR if corrupted/invalid data found
+ */
+ status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
+
+ /**
+ * Gets the remaining byte count which is not currently parsed.
+ */
+ int (*get_remaining_byte_count) (parser_t *this);
+
+ /**
+ * Resets the current parser context.
+ */
+ void (*reset_context) (parser_t *this);
+
+ /**
+ * Destroys a parser_t object.
+ */
+ void (*destroy) (parser_t *this);
+};
+
+/**
+ * Constructor to create a parser_t object.
+ *
+ * @param data chunk of data to parse with this parser_t object
+ * @return parser_t object
+ */
+parser_t *parser_create(chunk_t data);
+
+#endif /** PARSER_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c
new file mode 100644
index 000000000..d31208abb
--- /dev/null
+++ b/src/libcharon/encoding/payloads/auth_payload.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "auth_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_auth_payload_t private_auth_payload_t;
+
+/**
+ * Private data of an auth_payload_t object.
+ *
+ */
+struct private_auth_payload_t {
+
+ /**
+ * Public auth_payload_t interface.
+ */
+ auth_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Method of the AUTH Data.
+ */
+ u_int8_t auth_method;
+
+ /**
+ * The contained auth data value.
+ */
+ chunk_t auth_data;
+};
+
+/**
+ * Encoding rules to parse or generate a AUTH payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_auth_payload_t.
+ */
+encoding_rule_t auth_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_auth_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_auth_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)},
+ /* 1 Byte AUTH type*/
+ { U_INT_8, offsetof(private_auth_payload_t, auth_method) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some auth data bytes, length is defined in PAYLOAD_LENGTH */
+ { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Auth Method ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Authentication Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_auth_payload_t *this)
+{
+ if (this->auth_method == 0 ||
+ (this->auth_method >= 4 && this->auth_method <= 8) ||
+ (this->auth_method >= 12 && this->auth_method <= 200))
+ {
+ /* reserved IDs */
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of auth_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = auth_payload_encodings;
+ *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_auth_payload_t *this)
+{
+ return AUTHENTICATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_auth_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_auth_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_auth_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of auth_payload_t.set_auth_method.
+ */
+static void set_auth_method (private_auth_payload_t *this, auth_method_t method)
+{
+ this->auth_method = method;
+}
+
+/**
+ * Implementation of auth_payload_t.get_auth_method.
+ */
+static auth_method_t get_auth_method (private_auth_payload_t *this)
+{
+ return (this->auth_method);
+}
+
+/**
+ * Implementation of auth_payload_t.set_data.
+ */
+static void set_data (private_auth_payload_t *this, chunk_t data)
+{
+ if (this->auth_data.ptr != NULL)
+ {
+ chunk_free(&(this->auth_data));
+ }
+ this->auth_data.ptr = clalloc(data.ptr,data.len);
+ this->auth_data.len = data.len;
+ this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
+}
+
+/**
+ * Implementation of auth_payload_t.get_data.
+ */
+static chunk_t get_data (private_auth_payload_t *this)
+{
+ return (this->auth_data);
+}
+
+/**
+ * Implementation of auth_payload_t.get_data_clone.
+ */
+static chunk_t get_data_clone (private_auth_payload_t *this)
+{
+ chunk_t cloned_data;
+ if (this->auth_data.ptr == NULL)
+ {
+ return (this->auth_data);
+ }
+ cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len);
+ cloned_data.len = this->auth_data.len;
+ return cloned_data;
+}
+
+/**
+ * Implementation of payload_t.destroy and auth_payload_t.destroy.
+ */
+static void destroy(private_auth_payload_t *this)
+{
+ if (this->auth_data.ptr != NULL)
+ {
+ chunk_free(&(this->auth_data));
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+auth_payload_t *auth_payload_create()
+{
+ private_auth_payload_t *this = malloc_thing(private_auth_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (auth_payload_t *)) destroy;
+ this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method;
+ this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method;
+ this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data;
+ this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone;
+ this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH;
+ this->auth_data = chunk_empty;
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/auth_payload.h b/src/libcharon/encoding/payloads/auth_payload.h
new file mode 100644
index 000000000..37ee149db
--- /dev/null
+++ b/src/libcharon/encoding/payloads/auth_payload.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup auth_payload auth_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef AUTH_PAYLOAD_H_
+#define AUTH_PAYLOAD_H_
+
+typedef struct auth_payload_t auth_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <sa/authenticators/authenticator.h>
+
+/**
+ * Length of a auth payload without the auth data in bytes.
+ */
+#define AUTH_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 AUTH payload.
+ *
+ * The AUTH payload format is described in RFC section 3.8.
+ */
+struct auth_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the AUTH method.
+ *
+ * @param method auth_method_t to use
+ */
+ void (*set_auth_method) (auth_payload_t *this, auth_method_t method);
+
+ /**
+ * Get the AUTH method.
+ *
+ * @return auth_method_t used
+ */
+ auth_method_t (*get_auth_method) (auth_payload_t *this);
+
+ /**
+ * Set the AUTH data.
+ *
+ * Data gets cloned.
+ *
+ * @param data AUTH data as chunk_t
+ */
+ void (*set_data) (auth_payload_t *this, chunk_t data);
+
+ /**
+ * Get the AUTH data.
+ *
+ * Returned data are a copy of the internal one.
+ *
+ * @return AUTH data as chunk_t
+ */
+ chunk_t (*get_data_clone) (auth_payload_t *this);
+
+ /**
+ * Get the AUTH data.
+ *
+ * Returned data are NOT copied
+ *
+ * @return AUTH data as chunk_t
+ */
+ chunk_t (*get_data) (auth_payload_t *this);
+
+ /**
+ * Destroys an auth_payload_t object.
+ */
+ void (*destroy) (auth_payload_t *this);
+};
+
+/**
+ * Creates an empty auth_payload_t object.
+ *
+ * @return auth_payload_t object
+ */
+auth_payload_t *auth_payload_create(void);
+
+#endif /** AUTH_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
new file mode 100644
index 000000000..6dd3141f0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+#include <ctype.h>
+
+#include <daemon.h>
+
+#include "cert_payload.h"
+
+ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT,
+ "ENC_PKCS7_WRAPPED_X509",
+ "ENC_PGP",
+ "ENC_DNS_SIGNED_KEY",
+ "ENC_X509_SIGNATURE",
+ "ENC_X509_KEY_EXCHANGE",
+ "ENC_KERBEROS_TOKENS",
+ "ENC_CRL",
+ "ENC_ARL",
+ "ENC_SPKI",
+ "ENC_X509_ATTRIBUTE",
+ "ENC_RAW_RSA_KEY",
+ "ENC_X509_HASH_AND_URL",
+ "ENC_X509_HASH_AND_URL_BUNDLE",
+ "ENC_OCSP_CONTENT",
+);
+
+typedef struct private_cert_payload_t private_cert_payload_t;
+
+/**
+ * Private data of an cert_payload_t object.
+ *
+ */
+struct private_cert_payload_t {
+ /**
+ * Public cert_payload_t interface.
+ */
+ cert_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Encoding of the CERT Data.
+ */
+ u_int8_t encoding;
+
+ /**
+ * The contained cert data value.
+ */
+ chunk_t data;
+
+ /**
+ * TRUE if the "Hash and URL" data is invalid
+ */
+ bool invalid_hash_and_url;
+};
+
+/**
+ * Encoding rules to parse or generate a CERT payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_cert_payload_t.
+ *
+ */
+encoding_rule_t cert_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_cert_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
+ /* 1 Byte CERT type*/
+ { U_INT_8, offsetof(private_cert_payload_t, encoding) },
+ /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
+ { CERT_DATA, offsetof(private_cert_payload_t, data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Cert Encoding ! !
+ +-+-+-+-+-+-+-+-+ !
+ ~ Certificate Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_cert_payload_t *this)
+{
+ if (this->encoding == ENC_X509_HASH_AND_URL ||
+ this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
+ {
+ /* coarse verification of "Hash and URL" encoded certificates */
+ if (this->data.len <= 20)
+ {
+ DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
+ this->data.len);
+ this->invalid_hash_and_url = TRUE;
+ return SUCCESS;
+ }
+
+ int i = 20; /* skipping the hash */
+ for (; i < this->data.len; ++i)
+ {
+ if (this->data.ptr[i] == '\0')
+ {
+ /* null terminated, fine */
+ return SUCCESS;
+ }
+ else if (!isprint(this->data.ptr[i]))
+ {
+ DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
+ " encoded certificate payload, ignore");
+ this->invalid_hash_and_url = TRUE;
+ return SUCCESS;
+ }
+ }
+
+ /* URL is not null terminated, correct that */
+ chunk_t data = chunk_alloc(this->data.len + 1);
+ memcpy(data.ptr, this->data.ptr, this->data.len);
+ data.ptr[this->data.len] = '\0';
+ chunk_free(&this->data);
+ this->data = data;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of cert_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_cert_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = cert_payload_encodings;
+ *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_cert_payload_t *this)
+{
+ return CERTIFICATE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_cert_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_cert_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_cert_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of cert_payload_t.get_cert_encoding.
+ */
+static cert_encoding_t get_cert_encoding(private_cert_payload_t *this)
+{
+ return this->encoding;
+}
+
+/**
+ * Implementation of cert_payload_t.get_cert.
+ */
+static certificate_t *get_cert(private_cert_payload_t *this)
+{
+ if (this->encoding != ENC_X509_SIGNATURE)
+ {
+ return NULL;
+ }
+ return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, this->data,
+ BUILD_END);
+}
+
+/**
+ * Implementation of cert_payload_t.get_hash.
+ */
+static chunk_t get_hash(private_cert_payload_t *this)
+{
+ chunk_t hash = chunk_empty;
+ if ((this->encoding != ENC_X509_HASH_AND_URL &&
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->invalid_hash_and_url)
+ {
+ return hash;
+ }
+ hash.ptr = this->data.ptr;
+ hash.len = 20;
+ return hash;
+}
+
+/**
+ * Implementation of cert_payload_t.get_url.
+ */
+static char *get_url(private_cert_payload_t *this)
+{
+ if ((this->encoding != ENC_X509_HASH_AND_URL &&
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->invalid_hash_and_url)
+ {
+ return NULL;
+ }
+ return (char*)this->data.ptr + 20;
+}
+
+/**
+ * Implementation of payload_t.destroy and cert_payload_t.destroy.
+ */
+static void destroy(private_cert_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create()
+{
+ private_cert_payload_t *this = malloc_thing(private_cert_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**, size_t*))get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
+
+ this->public.destroy = (void (*) (cert_payload_t*))destroy;
+ this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert;
+ this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding;
+ this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash;
+ this->public.get_url = (char* (*) (cert_payload_t*))get_url;
+
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+ this->encoding = 0;
+ this->invalid_hash_and_url = FALSE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
+{
+ private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+
+ switch (cert->get_type(cert))
+ {
+ case CERT_X509:
+ this->encoding = ENC_X509_SIGNATURE;
+ break;
+ default:
+ DBG1(DBG_ENC, "embedding %N certificate in payload failed",
+ certificate_type_names, cert->get_type(cert));
+ free(this);
+ return NULL;
+ }
+ this->data = cert->get_encoding(cert);
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
+{
+ private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+
+ this->encoding = ENC_X509_HASH_AND_URL;
+ this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/cert_payload.h b/src/libcharon/encoding/payloads/cert_payload.h
new file mode 100644
index 000000000..aa1c7bf5a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cert_payload.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup cert_payload cert_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CERT_PAYLOAD_H_
+#define CERT_PAYLOAD_H_
+
+typedef struct cert_payload_t cert_payload_t;
+typedef enum cert_encoding_t cert_encoding_t;
+
+#include <library.h>
+#include <credentials/certificates/certificate.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a cert payload without the cert data in bytes.
+ */
+#define CERT_PAYLOAD_HEADER_LENGTH 5
+
+/**
+ * Certifcate encodings, as in RFC4306
+ */
+enum cert_encoding_t {
+ ENC_PKCS7_WRAPPED_X509 = 1,
+ ENC_PGP = 2,
+ ENC_DNS_SIGNED_KEY = 3,
+ ENC_X509_SIGNATURE = 4,
+ ENC_KERBEROS_TOKEN = 6,
+ ENC_CRL = 7,
+ ENC_ARL = 8,
+ ENC_SPKI = 9,
+ ENC_X509_ATTRIBUTE = 10,
+ ENC_RAW_RSA_KEY = 11,
+ ENC_X509_HASH_AND_URL = 12,
+ ENC_X509_HASH_AND_URL_BUNDLE = 13,
+ ENC_OCSP_CONTENT = 14, /* from RFC 4806 */
+};
+
+/**
+ * Enum names for cert_encoding_t
+ */
+extern enum_name_t *cert_encoding_names;
+
+/**
+ * Class representing an IKEv2 CERT payload.
+ *
+ * The CERT payload format is described in RFC section 3.6.
+ */
+struct cert_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the playoads encoded certifcate.
+ *
+ * @return certifcate copy
+ */
+ certificate_t *(*get_cert)(cert_payload_t *this);
+
+ /**
+ * Get the encoding of the certificate.
+ *
+ * @return encoding
+ */
+ cert_encoding_t (*get_cert_encoding)(cert_payload_t *this);
+
+ /**
+ * Get the hash if this is a hash and URL encoded certificate.
+ *
+ * This function returns internal data, do not free.
+ *
+ * @return hash
+ */
+ chunk_t (*get_hash)(cert_payload_t *this);
+
+ /**
+ * Get the URL if this is a hash and URL encoded certificate.
+ *
+ * This function returns internal data, do not free.
+ *
+ * @return url
+ */
+ char *(*get_url)(cert_payload_t *this);
+
+
+ /**
+ * Destroys the cert_payload object.
+ */
+ void (*destroy) (cert_payload_t *this);
+};
+
+/**
+ * Creates an empty certificate payload.
+ *
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create(void);
+
+/**
+ * Creates a certificate payload with an embedded certificate.
+ *
+ * @param cert certificate to embed
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create_from_cert(certificate_t *cert);
+
+/**
+ * Creates a certificate payload with hash and URL encoding of a certificate.
+ *
+ * @param hash hash of the DER encoded certificate (get's cloned)
+ * @param url the URL to locate the certificate (get's cloned)
+ * @return cert_payload_t object
+ */
+cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
+
+#endif /** CERT_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
new file mode 100644
index 000000000..9ff0bdde0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include <daemon.h>
+#include <crypto/hashers/hasher.h>
+#include <encoding/payloads/cert_payload.h>
+
+#include "certreq_payload.h"
+
+
+typedef struct private_certreq_payload_t private_certreq_payload_t;
+
+/**
+ * Private data of an certreq_payload_t object.
+ *
+ */
+struct private_certreq_payload_t {
+ /**
+ * Public certreq_payload_t interface.
+ */
+ certreq_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Encoding of the CERT Data.
+ */
+ u_int8_t encoding;
+
+ /**
+ * The contained certreq data value.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a CERTREQ payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_certreq_payload_t.
+ *
+ */
+encoding_rule_t certreq_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_certreq_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length) },
+ /* 1 Byte CERTREQ type*/
+ { U_INT_8, offsetof(private_certreq_payload_t, encoding) },
+ /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
+ { CERTREQ_DATA, offsetof(private_certreq_payload_t, data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Cert Encoding ! !
+ +-+-+-+-+-+-+-+-+ !
+ ~ Certification Authority ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_certreq_payload_t *this)
+{
+ if (this->encoding == ENC_X509_SIGNATURE)
+ {
+ if (this->data.len < HASH_SIZE_SHA1 ||
+ this->data.len % HASH_SIZE_SHA1)
+ {
+ DBG1(DBG_ENC, "invalid X509 hash length (%d) in certreq",
+ this->data.len);
+ return FAILED;
+ }
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of certreq_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = certreq_payload_encodings;
+ *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_certreq_payload_t *this)
+{
+ return CERTIFICATE_REQUEST;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_certreq_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_certreq_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_certreq_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of certreq_payload_t.add_keyid.
+ */
+static void add_keyid(private_certreq_payload_t *this, chunk_t keyid)
+{
+ this->data = chunk_cat("mc", this->data, keyid);
+ this->payload_length += keyid.len;
+}
+
+typedef struct keyid_enumerator_t keyid_enumerator_t;
+
+/**
+ * enumerator to enumerate keyids
+ */
+struct keyid_enumerator_t {
+ enumerator_t public;
+ chunk_t full;
+ u_char *pos;
+};
+
+/**
+ * enumerate function for keyid_enumerator
+ */
+static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk)
+{
+ if (this->pos == NULL)
+ {
+ this->pos = this->full.ptr;
+ }
+ else
+ {
+ this->pos += HASH_SIZE_SHA1;
+ if (this->pos > (this->full.ptr + this->full.len - HASH_SIZE_SHA1))
+ {
+ this->pos = NULL;
+ }
+ }
+ if (this->pos)
+ {
+ chunk->ptr = this->pos;
+ chunk->len = HASH_SIZE_SHA1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of certreq_payload_t.create_keyid_enumerator.
+ */
+static enumerator_t* create_keyid_enumerator(private_certreq_payload_t *this)
+{
+ keyid_enumerator_t *enumerator = malloc_thing(keyid_enumerator_t);
+ enumerator->public.enumerate = (void*)keyid_enumerate;
+ enumerator->public.destroy = (void*)free;
+ enumerator->full = this->data;
+ enumerator->pos = NULL;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of certreq_payload_t.get_cert_type.
+ */
+static certificate_type_t get_cert_type(private_certreq_payload_t *this)
+{
+ switch (this->encoding)
+ {
+ case ENC_X509_SIGNATURE:
+ return CERT_X509;
+ default:
+ return CERT_ANY;
+ }
+}
+
+/**
+ * Implementation of payload_t.destroy and certreq_payload_t.destroy.
+ */
+static void destroy(private_certreq_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+certreq_payload_t *certreq_payload_create()
+{
+ private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**,size_t*))get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (certreq_payload_t*)) destroy;
+ this->public.create_keyid_enumerator = (enumerator_t*(*)(certreq_payload_t*))create_keyid_enumerator;
+ this->public.get_cert_type = (certificate_type_t(*)(certreq_payload_t*))get_cert_type;
+ this->public.add_keyid = (void(*)(certreq_payload_t*, chunk_t keyid))add_keyid;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+ this->encoding = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
+{
+ private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create();
+
+ switch (type)
+ {
+ case CERT_X509:
+ this->encoding = ENC_X509_SIGNATURE;
+ break;
+ default:
+ DBG1(DBG_ENC, "certificate type %N not supported in requests",
+ certificate_type_names, type);
+ free(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/certreq_payload.h b/src/libcharon/encoding/payloads/certreq_payload.h
new file mode 100644
index 000000000..914063628
--- /dev/null
+++ b/src/libcharon/encoding/payloads/certreq_payload.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup certreq_payload certreq_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CERTREQ_PAYLOAD_H_
+#define CERTREQ_PAYLOAD_H_
+
+typedef struct certreq_payload_t certreq_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/cert_payload.h>
+
+/**
+ * Length of a CERTREQ payload without the CERTREQ data in bytes.
+ */
+#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
+
+/**
+ * Class representing an IKEv2 CERTREQ payload.
+ *
+ * The CERTREQ payload format is described in RFC section 3.7.
+ */
+struct certreq_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Create an enumerator over contained keyids.
+ *
+ * @return enumerator over chunk_t's.
+ */
+ enumerator_t* (*create_keyid_enumerator)(certreq_payload_t *this);
+
+ /**
+ * Get the type of contained certificate keyids.
+ *
+ * @return certificate keyid type
+ */
+ certificate_type_t (*get_cert_type)(certreq_payload_t *this);
+
+ /**
+ * Add a certificates keyid to the payload.
+ *
+ * @param keyid keyid of the trusted certifcate
+ * @return
+ */
+ void (*add_keyid)(certreq_payload_t *this, chunk_t keyid);
+
+ /**
+ * Destroys an certreq_payload_t object.
+ */
+ void (*destroy) (certreq_payload_t *this);
+};
+
+/**
+ * Creates an empty certreq_payload_t object.
+ *
+ * @return certreq payload
+ */
+certreq_payload_t *certreq_payload_create(void);
+
+/**
+ * Creates an empty certreq_payload_t for a kind of certificates.
+ *
+ * @param type type of the added keyids
+ * @return certreq payload
+ */
+certreq_payload_t *certreq_payload_create_type(certificate_type_t type);
+
+#endif /** CERTREQ_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
new file mode 100644
index 000000000..9094fd44d
--- /dev/null
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "configuration_attribute.h"
+
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+#include <daemon.h>
+
+
+typedef struct private_configuration_attribute_t private_configuration_attribute_t;
+
+/**
+ * Private data of an configuration_attribute_t object.
+ *
+ */
+struct private_configuration_attribute_t {
+ /**
+ * Public configuration_attribute_t interface.
+ */
+ configuration_attribute_t public;
+
+ /**
+ * Type of the attribute.
+ */
+ u_int16_t type;
+
+ /**
+ * Length of the attribute.
+ */
+ u_int16_t length;
+
+ /**
+ * Attribute value as chunk.
+ */
+ chunk_t value;
+};
+
+/**
+ * Encoding rules to parse or generate a configuration attribute.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_configuration_attribute_t.
+ */
+encoding_rule_t configuration_attribute_encodings[] = {
+
+ { RESERVED_BIT, 0 },
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
+ /* Length of attribute value */
+ { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
+ /* Value of attribute if attribute format flag is zero */
+ { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !R| Attribute Type ! Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ Value ~
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_configuration_attribute_t *this)
+{
+ bool failed = FALSE;
+
+ if (this->length != this->value.len)
+ {
+ DBG1(DBG_ENC, "invalid attribute length");
+ return FAILED;
+ }
+
+ switch (this->type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ if (this->length != 0 && this->length != 4)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP4_SUBNET:
+ if (this->length != 0 && this->length != 8)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_SUBNET:
+ if (this->length != 0 && this->length != 17)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+ case INTERNAL_IP6_DHCP:
+ if (this->length != 0 && this->length != 16)
+ {
+ failed = TRUE;
+ }
+ break;
+ case SUPPORTED_ATTRIBUTES:
+ if (this->length % 2)
+ {
+ failed = TRUE;
+ }
+ break;
+ case APPLICATION_VERSION:
+ /* any length acceptable */
+ break;
+ default:
+ DBG1(DBG_ENC, "unknown attribute type %N",
+ configuration_attribute_type_names, this->type);
+ break;
+ }
+
+ if (failed)
+ {
+ DBG1(DBG_ENC, "invalid attribute length %d for %N",
+ this->length, configuration_attribute_type_names, this->type);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_configuration_attribute_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = configuration_attribute_encodings;
+ *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_configuration_attribute_t *this)
+{
+ return CONFIGURATION_ATTRIBUTE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_configuration_attribute_t *this)
+{
+ return NO_PAYLOAD;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_configuration_attribute_t *this,
+ payload_type_t type)
+{
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_length.
+ */
+static size_t get_length(private_configuration_attribute_t *this)
+{
+ return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_type.
+ */
+static configuration_attribute_type_t get_configuration_attribute_type(
+ private_configuration_attribute_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of configuration_attribute_t.get_value.
+ */
+static chunk_t get_value(private_configuration_attribute_t *this)
+{
+ return this->value;
+}
+
+/**
+ * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_configuration_attribute_t *this)
+{
+ free(this->value.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+configuration_attribute_t *configuration_attribute_create()
+{
+ private_configuration_attribute_t *this;
+
+ this = malloc_thing(private_configuration_attribute_t);
+ this->public.payload_interface.verify = (status_t(*)(payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void(*)(payload_t *, encoding_rule_t **, size_t *) )get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t(*)(payload_t *))get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t(*)(payload_t *))get_next_type;
+ this->public.payload_interface.set_next_type = (void(*)(payload_t *,payload_type_t))set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t(*)(payload_t *))get_type;
+ this->public.payload_interface.destroy = (void(*)(payload_t*))destroy;
+
+ this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
+ this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
+ this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
+
+ this->type = 0;
+ this->value = chunk_empty;
+ this->length = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+configuration_attribute_t *configuration_attribute_create_value(
+ configuration_attribute_type_t type, chunk_t value)
+{
+ private_configuration_attribute_t *this;
+
+ this = (private_configuration_attribute_t*)configuration_attribute_create();
+ this->type = ((u_int16_t)type) & 0x7FFF;
+ this->value = chunk_clone(value);
+ this->length = value.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.h b/src/libcharon/encoding/payloads/configuration_attribute.h
new file mode 100644
index 000000000..6e4b018bb
--- /dev/null
+++ b/src/libcharon/encoding/payloads/configuration_attribute.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup configuration_attribute configuration_attribute
+ * @{ @ingroup payloads
+ */
+
+#ifndef CONFIGURATION_ATTRIBUTE_H_
+#define CONFIGURATION_ATTRIBUTE_H_
+
+typedef struct configuration_attribute_t configuration_attribute_t;
+
+#include <library.h>
+#include <attributes/attributes.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Configuration attribute header length in bytes.
+ */
+#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2-CONFIGURATION Attribute.
+ *
+ * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
+ */
+struct configuration_attribute_t {
+
+ /**
+ * Implements payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of the attribute.
+ *
+ * @return type of the configuration attribute
+ */
+ configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
+
+ /**
+ * Returns the value of the attribute.
+ *
+ * @return chunk_t pointing to the internal value
+ */
+ chunk_t (*get_value) (configuration_attribute_t *this);
+
+ /**
+ * Destroys an configuration_attribute_t object.
+ */
+ void (*destroy) (configuration_attribute_t *this);
+};
+
+/**
+ * Creates an empty configuration attribute.
+ *
+ * @return created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create();
+
+/**
+ * Creates a configuration attribute with type and value.
+ *
+ * @param type type of configuration attribute
+ * @param value value, gets cloned
+ * @return created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create_value(
+ configuration_attribute_type_t type, chunk_t value);
+
+#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c
new file mode 100644
index 000000000..f0a26eee2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cp_payload.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "cp_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+ENUM(config_type_names, CFG_REQUEST, CFG_ACK,
+ "CFG_REQUEST",
+ "CFG_REPLY",
+ "CFG_SET",
+ "CFG_ACK",
+);
+
+typedef struct private_cp_payload_t private_cp_payload_t;
+
+/**
+ * Private data of an cp_payload_t object.
+ *
+ */
+struct private_cp_payload_t {
+ /**
+ * Public cp_payload_t interface.
+ */
+ cp_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * List of attributes, as configuration_attribute_t
+ */
+ linked_list_t *attributes;
+
+ /**
+ * Config Type.
+ */
+ u_int8_t type;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-CP Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_cp_payload_t.
+ *
+ */
+encoding_rule_t cp_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_cp_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_cp_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole CP payload*/
+ { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
+ /* Proposals are stored in a proposal substructure,
+ offset points to a linked_list_t pointer */
+ { U_INT_8, offsetof(private_cp_payload_t, type) },
+ { RESERVED_BYTE,0 },
+ { RESERVED_BYTE,0 },
+ { RESERVED_BYTE,0 },
+ { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! CFG Type ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Configuration Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_cp_payload_t *this)
+{
+ status_t status = SUCCESS;
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ status = attribute->verify(attribute);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_cp_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = cp_payload_encodings;
+ *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_cp_payload_t *this)
+{
+ return CONFIGURATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_cp_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_cp_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_cp_payload_t *this)
+{
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ this->payload_length += attribute->get_length(attribute);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_cp_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of cp_payload_t.create_attribute_enumerator.
+ */
+static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this)
+{
+ return this->attributes->create_enumerator(this->attributes);
+}
+
+/**
+ * Implementation of cp_payload_t.add_attribute.
+ */
+static void add_attribute(private_cp_payload_t *this,
+ configuration_attribute_t *attribute)
+{
+ this->attributes->insert_last(this->attributes, attribute);
+ compute_length(this);
+}
+
+/**
+ * Implementation of cp_payload_t.get_type.
+ */
+static config_type_t get_config_type(private_cp_payload_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of payload_t.destroy and cp_payload_t.destroy.
+ */
+static void destroy(private_cp_payload_t *this)
+{
+ this->attributes->destroy_offset(this->attributes,
+ offsetof(configuration_attribute_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+cp_payload_t *cp_payload_create()
+{
+ private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator;
+ this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute;
+ this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type;
+ this->public.destroy = (void (*)(cp_payload_t *))destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+ this->attributes = linked_list_create();
+ this->type = CFG_REQUEST;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+cp_payload_t *cp_payload_create_type(config_type_t type)
+{
+ private_cp_payload_t *this = (private_cp_payload_t*)cp_payload_create();
+
+ this->type = type;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/cp_payload.h b/src/libcharon/encoding/payloads/cp_payload.h
new file mode 100644
index 000000000..7dcf58f7e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/cp_payload.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup cp_payload cp_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef CP_PAYLOAD_H_
+#define CP_PAYLOAD_H_
+
+typedef enum config_type_t config_type_t;
+typedef struct cp_payload_t cp_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <utils/enumerator.h>
+
+/**
+ * CP_PAYLOAD length in bytes without any proposal substructure.
+ */
+#define CP_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Config Type of an Configuration Payload.
+ */
+enum config_type_t {
+ CFG_REQUEST = 1,
+ CFG_REPLY = 2,
+ CFG_SET = 3,
+ CFG_ACK = 4,
+};
+
+/**
+ * enum name for config_type_t.
+ */
+extern enum_name_t *config_type_names;
+
+/**
+ * Class representing an IKEv2-CP Payload.
+ *
+ * The CP Payload format is described in RFC section 3.15.
+ */
+struct cp_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored configuration_attribute_t objects.
+ *
+ * @return enumerator over configration_attribute_T
+ */
+ enumerator_t *(*create_attribute_enumerator) (cp_payload_t *this);
+
+ /**
+ * Adds a configuration attribute to the configuration payload.
+ *
+ * @param attribute attribute to add
+ */
+ void (*add_attribute)(cp_payload_t *this,
+ configuration_attribute_t *attribute);
+
+ /**
+ * Get the configuration payload type.
+ *
+ * @return type of configuration payload
+ */
+ config_type_t (*get_type) (cp_payload_t *this);
+
+ /**
+ * Destroys an cp_payload_t object.
+ */
+ void (*destroy) (cp_payload_t *this);
+};
+
+/**
+ * Creates an empty configuration payload
+ *
+ * @return empty configuration payload
+ */
+cp_payload_t *cp_payload_create();
+
+/**
+ * Creates an cp_payload_t with type and value
+ *
+ * @param config_type type of configuration payload to create
+ * @return created configuration payload
+ */
+cp_payload_t *cp_payload_create_type(config_type_t config_type);
+
+#endif /** CP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
new file mode 100644
index 000000000..97b4743b2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "delete_payload.h"
+
+
+typedef struct private_delete_payload_t private_delete_payload_t;
+
+/**
+ * Private data of an delete_payload_t object.
+ *
+ */
+struct private_delete_payload_t {
+ /**
+ * Public delete_payload_t interface.
+ */
+ delete_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Protocol ID.
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * SPI Size.
+ */
+ u_int8_t spi_size;
+
+ /**
+ * Number of SPI's.
+ */
+ u_int16_t spi_count;
+
+ /**
+ * The contained SPI's.
+ */
+ chunk_t spis;
+
+ /**
+ * List containing u_int32_t spis
+ */
+ linked_list_t *spi_list;
+};
+
+/**
+ * Encoding rules to parse or generate a DELETE payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_delete_payload_t.
+ *
+ */
+encoding_rule_t delete_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_delete_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length)},
+ { U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
+ { U_INT_8, offsetof(private_delete_payload_t, spi_size) },
+ { U_INT_16, offsetof(private_delete_payload_t, spi_count) },
+ /* some delete data bytes, length is defined in PAYLOAD_LENGTH */
+ { SPIS, offsetof(private_delete_payload_t, spis) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Protocol ID ! SPI Size ! # of SPIs !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index(es) (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_delete_payload_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi_size != 4)
+ {
+ return FAILED;
+ }
+ break;
+ case PROTO_IKE:
+ case 0:
+ /* IKE deletion has no spi assigned! */
+ if (this->spi_size != 0)
+ {
+ return FAILED;
+ }
+ break;
+ default:
+ return FAILED;
+ }
+ if (this->spis.len != (this->spi_count * this->spi_size))
+ {
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of delete_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = delete_payload_encodings;
+ *rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_delete_payload_t *this)
+{
+ return DELETE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_delete_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_delete_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_delete_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of delete_payload_t.get_protocol_id.
+ */
+static protocol_id_t get_protocol_id (private_delete_payload_t *this)
+{
+ return (this->protocol_id);
+}
+
+/**
+ * Implementation of delete_payload_t.add_spi.
+ */
+static void add_spi(private_delete_payload_t *this, u_int32_t spi)
+{
+ /* only add SPIs if AH|ESP, ignore others */
+ if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
+ {
+ this->spi_count += 1;
+ this->spis.len += this->spi_size;
+ this->spis.ptr = realloc(this->spis.ptr, this->spis.len);
+ *(u_int32_t*)(this->spis.ptr + (this->spis.len / this->spi_size - 1)) = spi;
+ if (this->spi_list)
+ {
+ /* reset SPI iterator list */
+ this->spi_list->destroy(this->spi_list);
+ this->spi_list = NULL;
+ }
+ }
+}
+
+/**
+ * Implementation of delete_payload_t.create_spi_iterator.
+ */
+static iterator_t* create_spi_iterator(private_delete_payload_t *this)
+{
+ int i;
+
+ if (this->spi_list == NULL)
+ {
+ this->spi_list = linked_list_create();
+ /* only parse SPIs if AH|ESP */
+ if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
+ {
+ for (i = 0; i < this->spi_count; i++)
+ {
+ this->spi_list->insert_last(this->spi_list, this->spis.ptr + i *
+ this->spi_size);
+ }
+ }
+ }
+ return this->spi_list->create_iterator(this->spi_list, TRUE);
+}
+
+/**
+ * Implementation of payload_t.destroy and delete_payload_t.destroy.
+ */
+static void destroy(private_delete_payload_t *this)
+{
+ if (this->spis.ptr != NULL)
+ {
+ chunk_free(&this->spis);
+ }
+ if (this->spi_list)
+ {
+ this->spi_list->destroy(this->spi_list);
+ }
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
+{
+ private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (delete_payload_t *)) destroy;
+ this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
+ this->public.add_spi = (void (*) (delete_payload_t *,u_int32_t))add_spi;
+ this->public.create_spi_iterator = (iterator_t* (*) (delete_payload_t *)) create_spi_iterator;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH;
+ this->protocol_id = protocol_id;
+ this->spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0;
+ this->spi_count = 0;
+ this->spis = chunk_empty;
+ this->spi_list = NULL;
+
+ return (&this->public);
+}
diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h
new file mode 100644
index 000000000..3b62c1af1
--- /dev/null
+++ b/src/libcharon/encoding/payloads/delete_payload.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup delete_payload delete_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef DELETE_PAYLOAD_H_
+#define DELETE_PAYLOAD_H_
+
+typedef struct delete_payload_t delete_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+
+/**
+ * Length of a delete payload without the SPI in bytes.
+ */
+#define DELETE_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 DELETE payload.
+ *
+ * The DELETE payload format is described in RFC section 3.11.
+ */
+struct delete_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the protocol ID.
+ *
+ * @return protocol ID
+ */
+ protocol_id_t (*get_protocol_id) (delete_payload_t *this);
+
+ /**
+ * Add an SPI to the list of deleted SAs.
+ *
+ * @param spi spi to add
+ */
+ void (*add_spi) (delete_payload_t *this, u_int32_t spi);
+
+ /**
+ * Get an iterator over the SPIs.
+ *
+ * The iterate() function returns a pointer to a u_int32_t SPI.
+ *
+ * @return iterator over SPIs
+ */
+ iterator_t *(*create_spi_iterator) (delete_payload_t *this);
+
+ /**
+ * Destroys an delete_payload_t object.
+ */
+ void (*destroy) (delete_payload_t *this);
+};
+
+/**
+ * Creates an empty delete_payload_t object.
+ *
+ * @param protocol_id protocol, such as AH|ESP
+ * @return delete_payload_t object
+ */
+delete_payload_t *delete_payload_create(protocol_id_t protocol_id);
+
+#endif /** DELETE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
new file mode 100644
index 000000000..21f34a642
--- /dev/null
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "eap_payload.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_payload_t private_eap_payload_t;
+
+/**
+ * Private data of an eap_payload_t object.
+ *
+ */
+struct private_eap_payload_t {
+ /**
+ * Public eap_payload_t interface.
+ */
+ eap_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * EAP message data, if available
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a EAP payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_eap_payload_t.
+ *
+ */
+static encoding_rule_t eap_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_eap_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_eap_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
+ /* chunt to data, starting at "code" */
+ { EAP_DATA, offsetof(private_eap_payload_t, data) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Code ! Identifier ! Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Type ! Type_Data...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_eap_payload_t *this)
+{
+ u_int16_t length;
+ u_int8_t code;
+
+ if (this->data.len < 4)
+ {
+ DBG1(DBG_ENC, "EAP payloads EAP message too short (%d)", this->data.len);
+ return FAILED;
+ }
+ length = untoh16(this->data.ptr + 2);
+ if (this->data.len != length)
+ {
+ DBG1(DBG_ENC, "EAP payload length (%d) does not match contained "
+ "message length (%d)", this->data.len, length);
+ return FAILED;
+ }
+ code = this->data.ptr[0];
+ switch (code)
+ {
+ case EAP_REQUEST:
+ case EAP_RESPONSE:
+ {
+ if (this->data.len < 4)
+ {
+ DBG1(DBG_ENC, "EAP Request/Response does not have any data");
+ return FAILED;
+ }
+ break;
+ }
+ case EAP_SUCCESS:
+ case EAP_FAILURE:
+ {
+ if (this->data.len != 4)
+ {
+ DBG1(DBG_ENC, "EAP Success/Failure has data");
+ return FAILED;
+ }
+ break;
+ }
+ default:
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(payload_t, get_encoding_rules, void,
+ private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = eap_payload_encodings;
+ *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+METHOD(payload_t, get_payload_type, payload_type_t,
+ private_eap_payload_t *this)
+{
+ return EXTENSIBLE_AUTHENTICATION;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_eap_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_eap_payload_t *this, payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_eap_payload_t *this)
+{
+ return this->payload_length;
+}
+
+METHOD(eap_payload_t, get_data, chunk_t,
+ private_eap_payload_t *this)
+{
+ return this->data;
+}
+
+METHOD(eap_payload_t, set_data, void,
+ private_eap_payload_t *this, chunk_t data)
+{
+ free(this->data.ptr);
+ this->data = chunk_clone(data);
+ this->payload_length = this->data.len + 4;
+}
+
+METHOD(eap_payload_t, get_code, eap_code_t,
+ private_eap_payload_t *this)
+{
+ if (this->data.len > 0)
+ {
+ return this->data.ptr[0];
+ }
+ /* should not happen, as it is verified */
+ return 0;
+}
+
+METHOD(eap_payload_t, get_identifier, u_int8_t,
+ private_eap_payload_t *this)
+{
+ if (this->data.len > 1)
+ {
+ return this->data.ptr[1];
+ }
+ /* should not happen, as it is verified */
+ return 0;
+}
+
+METHOD(eap_payload_t, get_type, eap_type_t,
+ private_eap_payload_t *this, u_int32_t *vendor)
+{
+ eap_type_t type;
+
+ *vendor = 0;
+ if (this->data.len > 4)
+ {
+ type = this->data.ptr[4];
+ if (type != EAP_EXPANDED)
+ {
+ return type;
+ }
+ if (this->data.len >= 12)
+ {
+ *vendor = untoh32(this->data.ptr + 4) & 0x00FFFFFF;
+ return untoh32(this->data.ptr + 8);
+ }
+ }
+ return 0;
+}
+
+METHOD2(payload_t, eap_payload_t, destroy, void,
+ private_eap_payload_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create()
+{
+ private_eap_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_payload_type,
+ .destroy = _destroy,
+ },
+ .get_data = _get_data,
+ .set_data = _set_data,
+ .get_code = _get_code,
+ .get_identifier = _get_identifier,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = EAP_PAYLOAD_HEADER_LENGTH,
+ );
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_data(chunk_t data)
+{
+ eap_payload_t *this = eap_payload_create();
+
+ this->set_data(this, data);
+ return this;
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier)
+{
+ chunk_t data;
+
+ data = chunk_from_chars(code, identifier, 0, 0);
+ htoun16(data.ptr + 2, data.len);
+ return eap_payload_create_data(data);
+}
+
+/*
+ * Described in header
+ */
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier)
+{
+ chunk_t data;
+
+ data = chunk_from_chars(EAP_RESPONSE, identifier, 0, 0, EAP_NAK);
+ htoun16(data.ptr + 2, data.len);
+ return eap_payload_create_data(data);
+}
+
diff --git a/src/libcharon/encoding/payloads/eap_payload.h b/src/libcharon/encoding/payloads/eap_payload.h
new file mode 100644
index 000000000..0bde4b15e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/eap_payload.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_payload eap_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef EAP_PAYLOAD_H_
+#define EAP_PAYLOAD_H_
+
+typedef struct eap_payload_t eap_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Length of a EAP payload without the EAP Message in bytes.
+ */
+#define EAP_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2 EAP payload.
+ *
+ * The EAP payload format is described in RFC section 3.16.
+ */
+struct eap_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the contained EAP data.
+ *
+ * This contains the FULL EAP message starting with "code".
+ * Chunk gets cloned.
+ *
+ * @param message EAP data
+ */
+ void (*set_data) (eap_payload_t *this, chunk_t data);
+
+ /**
+ * Get the contained EAP data.
+ *
+ * This contains the FULL EAP message starting with "code".
+ *
+ * @return EAP data (pointer to internal data)
+ */
+ chunk_t (*get_data) (eap_payload_t *this);
+
+ /**
+ * Get the EAP code.
+ *
+ * @return EAP message as chunk_t
+ */
+ eap_code_t (*get_code) (eap_payload_t *this);
+
+ /**
+ * Get the EAP identifier.
+ *
+ * @return unique identifier
+ */
+ u_int8_t (*get_identifier) (eap_payload_t *this);
+
+ /**
+ * Get the EAP method type.
+ *
+ * @param vendor pointer receiving vendor identifier
+ * @return EAP method type, vendor specific if vendor != 0
+ */
+ eap_type_t (*get_type) (eap_payload_t *this, u_int32_t *vendor);
+
+ /**
+ * Destroys an eap_payload_t object.
+ */
+ void (*destroy) (eap_payload_t *this);
+};
+
+/**
+ * Creates an empty eap_payload_t object.
+ *
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create(void);
+
+/**
+ * Creates an eap_payload_t object with data.
+ *
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_data(chunk_t data);
+
+/**
+ * Creates an eap_payload_t object with a code.
+ *
+ * Could should be either EAP_SUCCESS/EAP_FAILURE, use
+ * constructor above otherwise.
+ *
+ * @param code EAP status code
+ * @param identifier EAP identifier to use in payload
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier);
+
+/**
+ * Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK.
+ *
+ * @param identifier EAP identifier to use in payload
+ * @return eap_payload_t object
+ */
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier);
+
+#endif /** EAP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encodings.c b/src/libcharon/encoding/payloads/encodings.c
new file mode 100644
index 000000000..85caeda82
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encodings.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "encodings.h"
+
+ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA,
+ "U_INT_4",
+ "U_INT_8",
+ "U_INT_16",
+ "U_INT_32",
+ "RESERVED_BIT",
+ "RESERVED_BYTE",
+ "FLAG",
+ "PAYLOAD_LENGTH",
+ "HEADER_LENGTH",
+ "SPI_SIZE",
+ "SPI",
+ "KEY_EXCHANGE_DATA",
+ "NOTIFICATION_DATA",
+ "PROPOSALS",
+ "TRANSFORMS",
+ "TRANSFORM_ATTRIBUTES",
+ "CONFIGURATION_ATTRIBUTES",
+ "CONFIGURATION_ATTRIBUTE_VALUE",
+ "ATTRIBUTE_FORMAT",
+ "ATTRIBUTE_TYPE",
+ "ATTRIBUTE_LENGTH_OR_VALUE",
+ "CONFIGURATION_ATTRIBUTE_LENGTH",
+ "ATTRIBUTE_VALUE",
+ "TRAFFIC_SELECTORS",
+ "TS_TYPE",
+ "ADDRESS",
+ "NONCE_DATA",
+ "ID_DATA",
+ "AUTH_DATA",
+ "CERT_DATA",
+ "CERTREQ_DATA",
+ "EAP_DATA",
+ "SPIS",
+ "VID_DATA",
+ "UNKNOWN_DATA",
+ "IKE_SPI",
+ "ENCRYPTED_DATA",
+);
diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h
new file mode 100644
index 000000000..52af4a984
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encodings.h
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup encodings encodings
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENCODINGS_H_
+#define ENCODINGS_H_
+
+typedef enum encoding_type_t encoding_type_t;
+typedef struct encoding_rule_t encoding_rule_t;
+
+#include <library.h>
+
+/**
+ * All different kinds of encoding types.
+ *
+ * Each field of an IKEv2-Message (in header or payload)
+ * which has to be parsed or generated differently has its own
+ * type defined here.
+ *
+ * Header is parsed like a payload and gets its one payload_id
+ * from PRIVATE USE space. Also the substructures
+ * of specific payload types get their own payload_id
+ * from PRIVATE_USE space. See IKEv2-Draft for more informations.
+ */
+enum encoding_type_t {
+
+ /**
+ * Representing a 4 Bit unsigned int value.
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 4 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 4 bit forward afterwards.
+ */
+ U_INT_4,
+
+ /**
+ * Representing a 8 Bit unsigned int value.
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 8 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 8 bit forward afterwards.
+ */
+ U_INT_8,
+
+ /**
+ * Representing a 16 Bit unsigned int value.
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ U_INT_16,
+
+ /**
+ * Representing a 32 Bit unsigned int value.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 32 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 32 bit forward afterwards.
+ */
+ U_INT_32,
+
+ /**
+ * represents a RESERVED_BIT used in FLAG-Bytes.
+ *
+ * When generating, the next bit is set to zero and the current write
+ * position is moved one bit forward.
+ * No value is read from the associated data struct.
+ * The current write position is moved 1 bit forward afterwards.
+ *
+ * When parsing, the current read pointer is moved one bit forward.
+ * No value is written to the associated data struct.
+ * The current read pointer is moved 1 bit forward afterwards.
+ */
+ RESERVED_BIT,
+
+ /**
+ * represents a RESERVED_BYTE.
+ *
+ * When generating, the next byte is set to zero and the current write
+ * position is moved one byte forward.
+ * No value is read from the associated data struct.
+ * The current write position is moved 1 byte forward afterwards.
+ *
+ * When parsing, the current read pointer is moved one byte forward.
+ * No value is written to the associated data struct.
+ * The current read pointer is moved 1 byte forward afterwards.
+ */
+ RESERVED_BYTE,
+
+ /**
+ * Representing a 1 Bit flag.
+ *
+ * When generation, the next bit is set to 1 if the associated value
+ * in the data struct is TRUE, 0 otherwise. The current write position
+ * is moved 1 bit forward afterwards.
+ *
+ * When parsing, the next bit is read and stored in the associated data
+ * struct. 0 means FALSE, 1 means TRUE, The current read pointer
+ * is moved 1 bit forward afterwards
+ */
+ FLAG,
+
+ /**
+ * Representating a length field of a payload.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ PAYLOAD_LENGTH,
+
+ /**
+ * Representating a length field of a header.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 32 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 32 bit forward afterwards.
+ */
+ HEADER_LENGTH,
+
+ /**
+ * Representating a spi size field.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 8 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 8 bit forward afterwards.
+ */
+ SPI_SIZE,
+
+ /**
+ * Representating a spi field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
+ */
+ SPI,
+
+ /**
+ * Representating a Key Exchange Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
+ */
+ KEY_EXCHANGE_DATA,
+
+ /**
+ * Representating a Notification field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
+ */
+ NOTIFICATION_DATA,
+
+ /**
+ * Representating one or more proposal substructures.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the proposal_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed proposal_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ PROPOSALS,
+
+ /**
+ * Representating one or more transform substructures.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the transform_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed transform_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRANSFORMS,
+
+ /**
+ * Representating one or more Attributes of a transform substructure.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the transform_attribute_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed transform_attribute_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRANSFORM_ATTRIBUTES,
+
+ /**
+ * Representating one or more Attributes of a configuration payload.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the configuration_attribute_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed configuration_attribute_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ CONFIGURATION_ATTRIBUTES,
+
+ /**
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ CONFIGURATION_ATTRIBUTE_VALUE,
+
+ /**
+ * Representing a 1 Bit flag specifying the format of a transform attribute.
+ *
+ * When generation, the next bit is set to 1 if the associated value
+ * in the data struct is TRUE, 0 otherwise. The current write position
+ * is moved 1 bit forward afterwards.
+ *
+ * When parsing, the next bit is read and stored in the associated data
+ * struct. 0 means FALSE, 1 means TRUE, The current read pointer
+ * is moved 1 bit forward afterwards.
+ */
+ ATTRIBUTE_FORMAT,
+ /**
+ * Representing a 15 Bit unsigned int value used as attribute type
+ * in an attribute transform.
+ *
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 15 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 15 bit forward afterwards.
+ */
+ ATTRIBUTE_TYPE,
+
+ /**
+ * Depending on the field of type ATTRIBUTE_FORMAT
+ * this field contains the length or the value of an transform attribute.
+ * Its stored in a 16 unsigned integer field.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ ATTRIBUTE_LENGTH_OR_VALUE,
+
+ /**
+ * This field contains the length or the value of an configuration attribute.
+ * Its stored in a 16 unsigned integer field.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ CONFIGURATION_ATTRIBUTE_LENGTH,
+
+ /**
+ * Depending on the field of type ATTRIBUTE_FORMAT
+ * this field is available or missing and so parsed/generated
+ * or not parsed/not generated.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
+ */
+ ATTRIBUTE_VALUE,
+
+ /**
+ * Representating one or more Traffic selectors of a TS payload.
+ *
+ * The offset points to a linked_list_t pointer.
+ *
+ * When generating the traffic_selector_substructure_t objects are stored
+ * in the pointed linked_list.
+ *
+ * When parsing the parsed traffic_selector_substructure_t objects have
+ * to be stored in the pointed linked_list.
+ */
+ TRAFFIC_SELECTORS,
+
+ /**
+ * Representating a Traffic selector type field.
+ *
+ * When generating it must be changed from host to network order.
+ * The value is read from the associated data struct.
+ * The current write position is moved 16 bit forward afterwards.
+ *
+ * When parsing it must be changed from network to host order.
+ * The value is written to the associated data struct.
+ * The current read pointer is moved 16 bit forward afterwards.
+ */
+ TS_TYPE,
+
+ /**
+ * Representating an address field in a traffic selector.
+ *
+ * Depending on the last field of type TS_TYPE
+ * this field is either 4 or 16 byte long.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing 4 or 16 bytes are read and written into the chunk pointing to.
+ */
+ ADDRESS,
+
+ /**
+ * Representating a Nonce Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ NONCE_DATA,
+
+ /**
+ * Representating a ID Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
+ */
+ ID_DATA,
+
+ /**
+ * Representating a AUTH Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
+ */
+ AUTH_DATA,
+
+ /**
+ * Representating a CERT Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
+ */
+ CERT_DATA,
+
+ /**
+ * Representating a CERTREQ Data field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
+ */
+ CERTREQ_DATA,
+
+ /**
+ * Representating an EAP message field.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ EAP_DATA,
+
+ /**
+ * Representating the SPIS field in a DELETE payload.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
+ */
+ SPIS,
+
+ /**
+ * Representating the VID DATA field in a VENDOR ID payload.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ VID_DATA,
+
+ /**
+ * Representating the DATA of an unknown payload.
+ *
+ * When generating the content of the chunkt pointing to
+ * is written.
+ *
+ * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ */
+ UNKNOWN_DATA,
+
+ /**
+ * Representating an IKE_SPI field in an IKEv2 Header.
+ *
+ * When generating the value of the u_int64_t pointing to
+ * is written (host and networ order is not changed).
+ *
+ * When parsing 8 bytes are read and written into the u_int64_t pointing to.
+ */
+ IKE_SPI,
+
+ /**
+ * Representing the encrypted data body of a encryption payload.
+ */
+ ENCRYPTED_DATA,
+};
+
+/**
+ * enum name for encoding_type_t
+ */
+extern enum_name_t *encoding_type_names;
+
+/**
+ * Rule how to en-/decode a payload field.
+ *
+ * An encoding rule is a mapping of a specific encoding type to
+ * a location in the data struct where the current field is stored to
+ * or read from.
+ * This rules are used by parser and generator.
+ */
+struct encoding_rule_t {
+
+ /**
+ * Encoding type.
+ */
+ encoding_type_t type;
+
+ /**
+ * Offset in the data struct.
+ *
+ * When parsing, data are written to this offset of the
+ * data struct.
+ *
+ * When generating, data are read from this offset in the
+ * data struct.
+ */
+ u_int32_t offset;
+};
+
+#endif /** ENCODINGS_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
new file mode 100644
index 000000000..2adbb88b9
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encryption_payload.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "encryption_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+#include <encoding/generator.h>
+#include <encoding/parser.h>
+#include <utils/iterator.h>
+#include <crypto/signers/signer.h>
+
+
+typedef struct private_encryption_payload_t private_encryption_payload_t;
+
+/**
+ * Private data of an encryption_payload_t' Object.
+ *
+ */
+struct private_encryption_payload_t {
+
+ /**
+ * Public encryption_payload_t interface.
+ */
+ encryption_payload_t public;
+
+ /**
+ * There is no next payload for an encryption payload,
+ * since encryption payload MUST be the last one.
+ * next_payload means here the first payload of the
+ * contained, encrypted payload.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Chunk containing the iv, data, padding,
+ * and (an eventually not calculated) signature.
+ */
+ chunk_t encrypted;
+
+ /**
+ * Chunk containing the data in decrypted (unpadded) form.
+ */
+ chunk_t decrypted;
+
+ /**
+ * Signer set by set_signer.
+ */
+ signer_t *signer;
+
+ /**
+ * Crypter, supplied by encrypt/decrypt
+ */
+ crypter_t *crypter;
+
+ /**
+ * Contained payloads of this encrpytion_payload.
+ */
+ linked_list_t *payloads;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Encryption Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encryption_payload_t.
+ *
+ */
+encoding_rule_t encryption_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_encryption_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole encryption payload*/
+ { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
+ /* encrypted data, stored in a chunk. contains iv, data, padding */
+ { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Initialization Vector !
+ ! (length is block size for encryption algorithm) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
+ ! ! Pad Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ Integrity Checksum Data ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_encryption_payload_t *this)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = encryption_payload_encodings;
+ *rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_encryption_payload_t *this)
+{
+ return ENCRYPTED;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_encryption_payload_t *this)
+{
+ /* returns first contained payload here */
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_encryption_payload_t *this, payload_type_t type)
+{
+ /* set next type is not allowed, since this payload MUST be the last one
+ * and so nothing is done in here*/
+}
+
+/**
+ * (re-)compute the lenght of the whole payload
+ */
+static void compute_length(private_encryption_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_payload;
+ size_t block_size, length = 0;
+ iterator = this->payloads->create_iterator(this->payloads, TRUE);
+
+ /* count payload length */
+ while (iterator->iterate(iterator, (void **) &current_payload))
+ {
+ length += current_payload->get_length(current_payload);
+ }
+ iterator->destroy(iterator);
+
+ if (this->crypter && this->signer)
+ {
+ /* append one byte for padding length */
+ length++;
+ /* append padding */
+ block_size = this->crypter->get_block_size(this->crypter);
+ length += block_size - length % block_size;
+ /* add iv */
+ length += block_size;
+ /* add signature */
+ length += this->signer->get_block_size(this->signer);
+ }
+ length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_encryption_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of payload_t.create_payload_iterator.
+ */
+static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward)
+{
+ return (this->payloads->create_iterator(this->payloads, forward));
+}
+
+/**
+ * Implementation of payload_t.add_payload.
+ */
+static void add_payload(private_encryption_payload_t *this, payload_t *payload)
+{
+ payload_t *last_payload;
+ if (this->payloads->get_count(this->payloads) > 0)
+ {
+ this->payloads->get_last(this->payloads,(void **) &last_payload);
+ last_payload->set_next_type(last_payload, payload->get_type(payload));
+ }
+ else
+ {
+ this->next_payload = payload->get_type(payload);
+ }
+ payload->set_next_type(payload, NO_PAYLOAD);
+ this->payloads->insert_last(this->payloads, (void*)payload);
+ compute_length(this);
+}
+
+/**
+ * Implementation of encryption_payload_t.remove_first_payload.
+ */
+static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload)
+{
+ return this->payloads->remove_first(this->payloads, (void**)payload);
+}
+
+/**
+ * Implementation of encryption_payload_t.get_payload_count.
+ */
+static size_t get_payload_count(private_encryption_payload_t *this)
+{
+ return this->payloads->get_count(this->payloads);
+}
+
+/**
+ * Generate payload before encryption.
+ */
+static void generate(private_encryption_payload_t *this)
+{
+ payload_t *current_payload, *next_payload;
+ generator_t *generator;
+ iterator_t *iterator;
+
+ /* recalculate length before generating */
+ compute_length(this);
+
+ /* create iterator */
+ iterator = this->payloads->create_iterator(this->payloads, TRUE);
+
+ /* get first payload */
+ if (iterator->iterate(iterator, (void**)&current_payload))
+ {
+ this->next_payload = current_payload->get_type(current_payload);
+ }
+ else
+ {
+ /* no paylads? */
+ DBG2(DBG_ENC, "generating contained payloads, but none available");
+ free(this->decrypted.ptr);
+ this->decrypted = chunk_empty;
+ iterator->destroy(iterator);
+ return;
+ }
+
+ generator = generator_create();
+
+ /* build all payload, except last */
+ while(iterator->iterate(iterator, (void**)&next_payload))
+ {
+ current_payload->set_next_type(current_payload, next_payload->get_type(next_payload));
+ generator->generate_payload(generator, current_payload);
+ current_payload = next_payload;
+ }
+ iterator->destroy(iterator);
+
+ /* build last payload */
+ current_payload->set_next_type(current_payload, NO_PAYLOAD);
+ generator->generate_payload(generator, current_payload);
+
+ /* free already generated data */
+ free(this->decrypted.ptr);
+
+ generator->write_to_chunk(generator, &(this->decrypted));
+ generator->destroy(generator);
+ DBG2(DBG_ENC, "successfully generated content in encryption payload");
+}
+
+/**
+ * Implementation of encryption_payload_t.encrypt.
+ */
+static status_t encrypt(private_encryption_payload_t *this)
+{
+ chunk_t iv, padding, to_crypt, result;
+ rng_t *rng;
+ size_t block_size;
+
+ if (this->signer == NULL || this->crypter == NULL)
+ {
+ DBG1(DBG_ENC, "could not encrypt, signer/crypter not set");
+ return INVALID_STATE;
+ }
+
+ /* for random data in iv and padding */
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_ENC, "could not encrypt, no RNG found");
+ return FAILED;
+ }
+ /* build payload chunk */
+ generate(this);
+
+ DBG2(DBG_ENC, "encrypting payloads");
+ DBG3(DBG_ENC, "data to encrypt %B", &this->decrypted);
+
+ /* build padding */
+ block_size = this->crypter->get_block_size(this->crypter);
+ padding.len = block_size - ((this->decrypted.len + 1) % block_size);
+ rng->allocate_bytes(rng, padding.len, &padding);
+
+ /* concatenate payload data, padding, padding len */
+ to_crypt.len = this->decrypted.len + padding.len + 1;
+ to_crypt.ptr = malloc(to_crypt.len);
+
+ memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len);
+ memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len);
+ *(to_crypt.ptr + to_crypt.len - 1) = padding.len;
+
+ /* build iv */
+ iv.len = block_size;
+ rng->allocate_bytes(rng, iv.len, &iv);
+ rng->destroy(rng);
+
+ DBG3(DBG_ENC, "data before encryption with padding %B", &to_crypt);
+
+ /* encrypt to_crypt chunk */
+ free(this->encrypted.ptr);
+ this->crypter->encrypt(this->crypter, to_crypt, iv, &result);
+ free(padding.ptr);
+ free(to_crypt.ptr);
+
+ DBG3(DBG_ENC, "data after encryption %B", &result);
+
+ /* build encrypted result with iv and signature */
+ this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
+ free(this->encrypted.ptr);
+ this->encrypted.ptr = malloc(this->encrypted.len);
+
+ /* fill in result, signature is left out */
+ memcpy(this->encrypted.ptr, iv.ptr, iv.len);
+ memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len);
+
+ free(result.ptr);
+ free(iv.ptr);
+ DBG3(DBG_ENC, "data after encryption with IV and (invalid) signature %B",
+ &this->encrypted);
+
+ return SUCCESS;
+}
+
+/**
+ * Parse the payloads after decryption.
+ */
+static status_t parse(private_encryption_payload_t *this)
+{
+ parser_t *parser;
+ status_t status;
+ payload_type_t current_payload_type;
+
+ /* build a parser on the decrypted data */
+ parser = parser_create(this->decrypted);
+
+ current_payload_type = this->next_payload;
+ /* parse all payloads */
+ while (current_payload_type != NO_PAYLOAD)
+ {
+ payload_t *current_payload;
+
+ status = parser->parse_payload(parser, current_payload_type, (payload_t**)&current_payload);
+ if (status != SUCCESS)
+ {
+ parser->destroy(parser);
+ return PARSE_ERROR;
+ }
+
+ status = current_payload->verify(current_payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N verification failed",
+ payload_type_names, current_payload->get_type(current_payload));
+ current_payload->destroy(current_payload);
+ parser->destroy(parser);
+ return VERIFY_ERROR;
+ }
+
+ /* get next payload type */
+ current_payload_type = current_payload->get_next_type(current_payload);
+
+ this->payloads->insert_last(this->payloads,current_payload);
+ }
+ parser->destroy(parser);
+ DBG2(DBG_ENC, "succesfully parsed content of encryption payload");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of encryption_payload_t.encrypt.
+ */
+static status_t decrypt(private_encryption_payload_t *this)
+{
+ chunk_t iv, concatenated;
+ u_int8_t padding_length;
+
+ DBG2(DBG_ENC, "decrypting encryption payload");
+ DBG3(DBG_ENC, "data before decryption with IV and (invalid) signature %B",
+ &this->encrypted);
+
+ if (this->signer == NULL || this->crypter == NULL)
+ {
+ DBG1(DBG_ENC, "could not decrypt, no crypter/signer set");
+ return INVALID_STATE;
+ }
+
+ /* get IV */
+ iv.len = this->crypter->get_block_size(this->crypter);
+
+ iv.ptr = this->encrypted.ptr;
+
+ /* point concatenated to data + padding + padding_length*/
+ concatenated.ptr = this->encrypted.ptr + iv.len;
+ concatenated.len = this->encrypted.len - iv.len -
+ this->signer->get_block_size(this->signer);
+
+ /* concatenated must be a multiple of block_size of crypter */
+ if (concatenated.len < iv.len || concatenated.len % iv.len)
+ {
+ DBG1(DBG_ENC, "could not decrypt, invalid input");
+ return FAILED;
+ }
+
+ /* free previus data, if any */
+ free(this->decrypted.ptr);
+
+ DBG3(DBG_ENC, "data before decryption %B", &concatenated);
+
+ this->crypter->decrypt(this->crypter, concatenated, iv, &this->decrypted);
+
+ DBG3(DBG_ENC, "data after decryption with padding %B", &this->decrypted);
+
+ /* get padding length, sits just bevore signature */
+ padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
+ /* add one byte to the padding length, since the padding_length field is
+ * not included */
+ padding_length++;
+
+ /* check size again */
+ if (padding_length > concatenated.len || padding_length > this->decrypted.len)
+ {
+ DBG1(DBG_ENC, "decryption failed, invalid padding length found. Invalid key?");
+ /* decryption failed :-/ */
+ return FAILED;
+ }
+ this->decrypted.len -= padding_length;
+
+ /* free padding */
+ this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len);
+ DBG3(DBG_ENC, "data after decryption without padding %B", &this->decrypted);
+ DBG2(DBG_ENC, "decryption successful, trying to parse content");
+ return parse(this);
+}
+
+/**
+ * Implementation of encryption_payload_t.set_transforms.
+ */
+static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer)
+{
+ this->signer = signer;
+ this->crypter = crypter;
+}
+
+/**
+ * Implementation of encryption_payload_t.build_signature.
+ */
+static status_t build_signature(private_encryption_payload_t *this, chunk_t data)
+{
+ chunk_t data_without_sig = data;
+ chunk_t sig;
+
+ if (this->signer == NULL)
+ {
+ DBG1(DBG_ENC, "unable to build signature, no signer set");
+ return INVALID_STATE;
+ }
+
+ sig.len = this->signer->get_block_size(this->signer);
+ data_without_sig.len -= sig.len;
+ sig.ptr = data.ptr + data_without_sig.len;
+ DBG2(DBG_ENC, "building signature");
+ this->signer->get_signature(this->signer, data_without_sig, sig.ptr);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of encryption_payload_t.verify_signature.
+ */
+static status_t verify_signature(private_encryption_payload_t *this, chunk_t data)
+{
+ chunk_t sig, data_without_sig;
+ bool valid;
+
+ if (this->signer == NULL)
+ {
+ DBG1(DBG_ENC, "unable to verify signature, no signer set");
+ return INVALID_STATE;
+ }
+ /* find signature in data chunk */
+ sig.len = this->signer->get_block_size(this->signer);
+ if (data.len <= sig.len)
+ {
+ DBG1(DBG_ENC, "unable to verify signature, invalid input");
+ return FAILED;
+ }
+ sig.ptr = data.ptr + data.len - sig.len;
+
+ /* verify it */
+ data_without_sig.len = data.len - sig.len;
+ data_without_sig.ptr = data.ptr;
+ valid = this->signer->verify_signature(this->signer, data_without_sig, sig);
+
+ if (!valid)
+ {
+ DBG1(DBG_ENC, "signature verification failed");
+ return FAILED;
+ }
+
+ DBG2(DBG_ENC, "signature verification successful");
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.destroy.
+ */
+static void destroy(private_encryption_payload_t *this)
+{
+ this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
+ free(this->encrypted.ptr);
+ free(this->decrypted.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+encryption_payload_t *encryption_payload_create()
+{
+ private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t);
+
+ /* payload_t interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator;
+ this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload;
+ this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload;
+ this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count;
+
+ this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt;
+ this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt;
+ this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms;
+ this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature;
+ this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature;
+ this->public.destroy = (void (*) (encryption_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH;
+ this->encrypted = chunk_empty;
+ this->decrypted = chunk_empty;
+ this->signer = NULL;
+ this->crypter = NULL;
+ this->payloads = linked_list_create();
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h
new file mode 100644
index 000000000..ac5326b87
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encryption_payload.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup encryption_payload encryption_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENCRYPTION_PAYLOAD_H_
+#define ENCRYPTION_PAYLOAD_H_
+
+typedef struct encryption_payload_t encryption_payload_t;
+
+#include <library.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <encoding/payloads/payload.h>
+#include <utils/linked_list.h>
+
+/**
+ * Encrpytion payload length in bytes without IV and following data.
+ */
+#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
+
+
+/**
+ * The encryption payload as described in RFC section 3.14.
+ *
+ * Before any crypt/decrypt/sign/verify operation can occur,
+ * the transforms must be set. After that, a parsed encryption payload
+ * can be decrypted, which also will parse the contained payloads.
+ * Encryption is done the same way, added payloads will get generated
+ * and then encrypted.
+ * For signature building, there is the FULL packet needed. Meaning it
+ * must be builded after generation of all payloads and the encryption
+ * of the encryption payload.
+ * Signature verificatin is done before decryption.
+ */
+struct encryption_payload_t {
+ /**
+ * Implements payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator for all contained payloads.
+ *
+ * iterator_t object has to get destroyed by the caller.
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * return created iterator_t object
+ */
+ iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward);
+
+ /**
+ * Adds a payload to this encryption payload.
+ *
+ * @param payload payload_t object to add
+ */
+ void (*add_payload) (encryption_payload_t *this, payload_t *payload);
+
+ /**
+ * Reove the last payload in the contained payload list.
+ *
+ * @param payload removed payload
+ * @return
+ * - SUCCESS, or
+ * - NOT_FOUND if list empty
+ */
+ status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload);
+
+ /**
+ * Get the number of payloads.
+ *
+ * @return number of contained payloads
+ */
+ size_t (*get_payload_count) (encryption_payload_t *this);
+
+ /**
+ * Set transforms to use.
+ *
+ * To decryption, encryption, signature building and verifying,
+ * the payload needs a crypter and a signer object.
+ *
+ * @warning Do NOT call this function again after encryption, since
+ * the signer must be the same while encrypting and signature building!
+ *
+ * @param crypter crypter_t to use for data de-/encryption
+ * @param signer signer_t to use for data signing/verifying
+ */
+ void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer);
+
+ /**
+ * Generate and encrypt contained payloads.
+ *
+ * This function generates the content for added payloads
+ * and encrypts them. Signature is not built, since we need
+ * additional data (the full message).
+ *
+ * @return SUCCESS, or INVALID_STATE if transforms not set
+ */
+ status_t (*encrypt) (encryption_payload_t *this);
+
+ /**
+ * Decrypt and parse contained payloads.
+ *
+ * This function decrypts the contained data. After,
+ * the payloads are parsed internally and are accessible
+ * via the iterator.
+ *
+ * @return
+ * - SUCCESS, or
+ * - INVALID_STATE if transforms not set, or
+ * - FAILED if data is invalid
+ */
+ status_t (*decrypt) (encryption_payload_t *this);
+
+ /**
+ * Build the signature.
+ *
+ * The signature is built over the FULL message, so the header
+ * and every payload (inclusive this one) must already be generated.
+ * The generated message is supplied via the data paramater.
+ *
+ * @param data chunk contains the already generated message
+ * @return
+ * - SUCCESS, or
+ * - INVALID_STATE if transforms not set
+ */
+ status_t (*build_signature) (encryption_payload_t *this, chunk_t data);
+
+ /**
+ * Verify the signature.
+ *
+ * Since the signature is built over the full message, we need
+ * this data to do the verification. The message data
+ * is supplied via the data argument.
+ *
+ * @param data chunk contains the message
+ * @return
+ * - SUCCESS, or
+ * - FAILED if signature invalid, or
+ * - INVALID_STATE if transforms not set
+ */
+ status_t (*verify_signature) (encryption_payload_t *this, chunk_t data);
+
+ /**
+ * Destroys an encryption_payload_t object.
+ */
+ void (*destroy) (encryption_payload_t *this);
+};
+
+/**
+ * Creates an empty encryption_payload_t object.
+ *
+ * @return encryption_payload_t object
+ */
+encryption_payload_t *encryption_payload_create(void);
+
+#endif /** ENCRYPTION_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.c b/src/libcharon/encoding/payloads/endpoint_notify.c
new file mode 100644
index 000000000..faec1ea71
--- /dev/null
+++ b/src/libcharon/encoding/payloads/endpoint_notify.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2007 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 "endpoint_notify.h"
+
+#include <math.h>
+
+#include <daemon.h>
+
+typedef struct private_endpoint_notify_t private_endpoint_notify_t;
+
+/**
+ * Private data of an notify_payload_t object.
+ */
+struct private_endpoint_notify_t {
+ /**
+ * Public endpoint_notify_t interface.
+ */
+ endpoint_notify_t public;
+
+ /**
+ * Priority
+ */
+ u_int32_t priority;
+
+ /**
+ * Family
+ */
+ me_endpoint_family_t family;
+
+ /**
+ * Endpoint type
+ */
+ me_endpoint_type_t type;
+
+ /**
+ * Endpoint
+ */
+ host_t *endpoint;
+
+ /**
+ * Base (used for server reflexive endpoints)
+ */
+ host_t *base;
+};
+
+/* Notification data:
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Priority !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Family ! Type ! Port !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IP Address (variable) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+ENUM(me_endpoint_type_names, HOST, RELAYED,
+ "HOST",
+ "PEER_REFLEXIVE",
+ "SERVER_REFLEXIVE",
+ "RELAYED"
+);
+
+/**
+ * Helper functions to parse integer values
+ */
+static status_t parse_uint8(u_int8_t **cur, u_int8_t *top, u_int8_t *val)
+{
+ if (*cur + sizeof(u_int8_t) > top)
+ {
+ return FAILED;
+ }
+ *val = *(u_int8_t*)*cur;
+ *cur += sizeof(u_int8_t);
+ return SUCCESS;
+}
+
+static status_t parse_uint16(u_int8_t **cur, u_int8_t *top, u_int16_t *val)
+{
+ if (*cur + sizeof(u_int16_t) > top)
+ {
+ return FAILED;
+ }
+ *val = ntohs(*(u_int16_t*)*cur);
+ *cur += sizeof(u_int16_t);
+ return SUCCESS;
+}
+
+static status_t parse_uint32(u_int8_t **cur, u_int8_t *top, u_int32_t *val)
+{
+ if (*cur + sizeof(u_int32_t) > top)
+ {
+ return FAILED;
+ }
+ *val = ntohl(*(u_int32_t*)*cur);
+ *cur += sizeof(u_int32_t);
+ return SUCCESS;
+}
+
+/**
+ * Parses the notification data of a ME_ENDPOINT notify
+ */
+static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
+{
+ u_int8_t family, type, addr_family;
+ u_int16_t port;
+ chunk_t addr;
+ u_int8_t *cur = data.ptr;
+ u_int8_t *top = data.ptr + data.len;
+
+ DBG3(DBG_IKE, "me_endpoint_data %B", &data);
+
+ if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority");
+ return FAILED;
+ }
+
+ if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family");
+ return FAILED;
+ }
+ this->family = (me_endpoint_family_t)family;
+
+ if (parse_uint8(&cur, top, &type) != SUCCESS ||
+ type == NO_TYPE || type >= MAX_TYPE)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type");
+ return FAILED;
+ }
+ this->type = (me_endpoint_type_t)type;
+
+ addr_family = AF_INET;
+ addr.len = 4;
+
+ switch(this->family)
+ {
+ case IPv6:
+ addr_family = AF_INET6;
+ addr.len = 16;
+ /* fall-through */
+ case IPv4:
+ if (parse_uint16(&cur, top, &port) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port");
+ return FAILED;
+ }
+
+ if (cur + addr.len > top)
+ {
+ DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address");
+ return FAILED;
+ }
+
+ addr.ptr = cur;
+ this->endpoint = host_create_from_chunk(addr_family, addr, port);
+ break;
+ case NO_FAMILY:
+ default:
+ this->endpoint = NULL;
+ break;
+ }
+ return SUCCESS;
+}
+
+
+/**
+ * Generates the notification data of a ME_ENDPOINT notify
+ */
+static chunk_t build_notification_data(private_endpoint_notify_t *this)
+{
+ chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
+ chunk_t data;
+ u_int32_t prio;
+ u_int16_t port;
+ u_int8_t family, type;
+
+ prio = htonl(this->priority);
+ prio_chunk = chunk_from_thing(prio);
+ family = this->family;
+ family_chunk = chunk_from_thing(family);
+ type = this->type;
+ type_chunk = chunk_from_thing(type);
+
+ if (this->endpoint)
+ {
+ port = htons(this->endpoint->get_port(this->endpoint));
+ addr_chunk = this->endpoint->get_address(this->endpoint);
+ }
+ else
+ {
+ port = 0;
+ addr_chunk = chunk_empty;
+ }
+ port_chunk = chunk_from_thing(port);
+
+ /* data = prio | family | type | port | addr */
+ data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
+ port_chunk, addr_chunk);
+ DBG3(DBG_IKE, "me_endpoint_data %B", &data);
+ return data;
+}
+
+/**
+ * Implementation of endpoint_notify_t.build_notify
+ */
+static notify_payload_t *build_notify(private_endpoint_notify_t *this)
+{
+ chunk_t data;
+ notify_payload_t *notify;
+
+ notify = notify_payload_create();
+ notify->set_notify_type(notify, ME_ENDPOINT);
+ data = build_notification_data(this);
+ notify->set_notification_data(notify, data);
+ chunk_free(&data);
+
+ return notify;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_priority.
+ */
+static u_int32_t get_priority(private_endpoint_notify_t *this)
+{
+ return this->priority;
+}
+
+/**
+ * Implementation of endpoint_notify_t.set_priority.
+ */
+static void set_priority(private_endpoint_notify_t *this, u_int32_t priority)
+{
+ this->priority = priority;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_type.
+ */
+static me_endpoint_type_t get_type(private_endpoint_notify_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_family.
+ */
+static me_endpoint_family_t get_family(private_endpoint_notify_t *this)
+{
+ return this->family;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_host.
+ */
+static host_t *get_host(private_endpoint_notify_t *this)
+{
+ return this->endpoint;
+}
+
+/**
+ * Implementation of endpoint_notify_t.get_base.
+ */
+static host_t *get_base(private_endpoint_notify_t *this)
+{
+ return (!this->base) ? this->endpoint : this->base;
+}
+
+/**
+ * Implementation of endpoint_notify_t.clone.
+ */
+static endpoint_notify_t *_clone(private_endpoint_notify_t *this)
+{
+ private_endpoint_notify_t *clone = (private_endpoint_notify_t*)endpoint_notify_create();
+
+ clone->priority = this->priority;
+ clone->type = this->type;
+ clone->family = this->family;
+ if (this->endpoint)
+ {
+ clone->endpoint = this->endpoint->clone(this->endpoint);
+ }
+
+ if (this->base)
+ {
+ clone->base = this->base->clone(this->base);
+ }
+
+ return &clone->public;
+}
+
+/**
+ * Implementation of endpoint_notify_t.destroy.
+ */
+static status_t destroy(private_endpoint_notify_t *this)
+{
+ DESTROY_IF(this->endpoint);
+ DESTROY_IF(this->base);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create()
+{
+ private_endpoint_notify_t *this = malloc_thing(private_endpoint_notify_t);
+
+ /* public functions */
+ this->public.get_priority = (u_int32_t (*) (endpoint_notify_t *)) get_priority;
+ this->public.set_priority = (void (*) (endpoint_notify_t *, u_int32_t)) set_priority;
+ this->public.get_type = (me_endpoint_type_t (*) (endpoint_notify_t *)) get_type;
+ this->public.get_family = (me_endpoint_family_t (*) (endpoint_notify_t *)) get_family;
+ this->public.get_host = (host_t *(*) (endpoint_notify_t *)) get_host;
+ this->public.get_base = (host_t *(*) (endpoint_notify_t *)) get_base;
+ this->public.build_notify = (notify_payload_t *(*) (endpoint_notify_t *)) build_notify;
+ this->public.clone = (endpoint_notify_t *(*) (endpoint_notify_t *)) _clone;
+ this->public.destroy = (void (*) (endpoint_notify_t *)) destroy;
+
+ /* set default values of the fields */
+ this->priority = 0;
+ this->family = NO_FAMILY;
+ this->type = NO_TYPE;
+ this->endpoint = NULL;
+ this->base = NULL;
+
+ return &this->public;
+}
+
+/**
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type, host_t *host, host_t *base)
+{
+ private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
+
+ this->type = type;
+
+ switch(type)
+ {
+ case HOST:
+ this->priority = pow(2, 16) * ME_PRIO_HOST;
+ break;
+ case PEER_REFLEXIVE:
+ this->priority = pow(2, 16) * ME_PRIO_PEER;
+ break;
+ case SERVER_REFLEXIVE:
+ this->priority = pow(2, 16) * ME_PRIO_SERVER;
+ break;
+ case RELAYED:
+ default:
+ this->priority = pow(2, 16) * ME_PRIO_RELAY;
+ break;
+ }
+
+ /* FIXME: if there is more than one ip address we should vary this priority */
+ this->priority += 65535;
+
+ if (!host)
+ {
+ return &this->public;
+ }
+
+ switch(host->get_family(host))
+ {
+ case AF_INET:
+ this->family = IPv4;
+ break;
+ case AF_INET6:
+ this->family = IPv6;
+ break;
+ default:
+ /* unsupported family type, we do not set the host
+ * (family is set to NO_FAMILY) */
+ return &this->public;
+ }
+
+ this->endpoint = host->clone(host);
+
+ if (base)
+ {
+ this->base = base->clone(base);
+ }
+
+ return &this->public;
+}
+
+/**
+ * Described in header
+ */
+endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
+{
+ if (notify->get_notify_type(notify) != ME_ENDPOINT)
+ {
+ return NULL;
+ }
+
+ private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
+ chunk_t data = notify->get_notification_data(notify);
+ if (parse_notification_data(this, data) != SUCCESS)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.h b/src/libcharon/encoding/payloads/endpoint_notify.h
new file mode 100644
index 000000000..120eef49a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/endpoint_notify.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2007 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 endpoint_notify endpoint_notify
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENDPOINT_NOTIFY_H_
+#define ENDPOINT_NOTIFY_H_
+
+#define ME_PRIO_HOST 255
+#define ME_PRIO_PEER 128
+#define ME_PRIO_SERVER 64
+#define ME_PRIO_RELAY 0
+
+typedef enum me_endpoint_family_t me_endpoint_family_t;
+typedef enum me_endpoint_type_t me_endpoint_type_t;
+typedef struct endpoint_notify_t endpoint_notify_t;
+
+#include <encoding/payloads/notify_payload.h>
+
+/**
+ * ME endpoint families.
+ */
+enum me_endpoint_family_t {
+
+ NO_FAMILY = 0,
+
+ IPv4 = 1,
+
+ IPv6 = 2,
+
+ MAX_FAMILY = 3
+
+};
+
+/**
+ * ME endpoint types.
+ */
+enum me_endpoint_type_t {
+
+ NO_TYPE = 0,
+
+ HOST = 1,
+
+ PEER_REFLEXIVE = 2,
+
+ SERVER_REFLEXIVE = 3,
+
+ RELAYED = 4,
+
+ MAX_TYPE = 5
+
+};
+
+/**
+ * enum name for me_endpoint_type_t.
+ */
+extern enum_name_t *me_endpoint_type_names;
+
+/**
+ * Class representing a ME_ENDPOINT Notify payload. In fact it's not
+ * the notify per se, but the notification data of that notify that is
+ * handled with this class.
+ */
+struct endpoint_notify_t {
+ /**
+ * Returns the priority of this endpoint.
+ *
+ * @return priority
+ */
+ u_int32_t (*get_priority) (endpoint_notify_t *this);
+
+ /**
+ * Sets the priority of this endpoint.
+ *
+ * @param priority priority
+ */
+ void (*set_priority) (endpoint_notify_t *this, u_int32_t priority);
+
+ /**
+ * Returns the endpoint type of this endpoint.
+ *
+ * @return endpoint type
+ */
+ me_endpoint_type_t (*get_type) (endpoint_notify_t *this);
+
+ /**
+ * Returns the endpoint family of this endpoint.
+ *
+ * @return endpoint family
+ */
+ me_endpoint_family_t (*get_family) (endpoint_notify_t *this);
+
+ /**
+ * Returns the host of this endpoint.
+ *
+ * @return host
+ */
+ host_t *(*get_host) (endpoint_notify_t *this);
+
+ /**
+ * Returns the base of this endpoint.
+ *
+ * If this is not a SERVER_REFLEXIVE endpoint, the returned host is the same
+ * as the one returned by get_host.
+ *
+ * @return host
+ */
+ host_t *(*get_base) (endpoint_notify_t *this);
+
+ /**
+ * Generates a notification payload from this endpoint.
+ *
+ * @return built notify_payload_t
+ */
+ notify_payload_t *(*build_notify) (endpoint_notify_t *this);
+
+ /**
+ * Clones an endpoint_notify_t object.
+ *
+ * @return cloned object
+ */
+ endpoint_notify_t *(*clone) (endpoint_notify_t *this);
+
+ /**
+ * Destroys an endpoint_notify_t object.
+ */
+ void (*destroy) (endpoint_notify_t *this);
+};
+
+/**
+ * Creates an empty endpoint_notify_t object.
+ *
+ * @return created endpoint_notify_t object
+ */
+endpoint_notify_t *endpoint_notify_create(void);
+
+
+/**
+ * Creates an endpoint_notify_t object from a host.
+ *
+ * @param type the endpoint type
+ * @param host host to base the notify on (gets cloned)
+ * @param base base of the endpoint, applies only to reflexive endpoints (gets cloned)
+ * @return created endpoint_notify_t object
+ */
+endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type,
+ host_t *host, host_t *base);
+
+/**
+ * Creates an endpoint_notify_t object from a notify payload.
+ *
+ * @param notify the notify payload
+ * @return - created endpoint_notify_t object
+ * - NULL if invalid payload
+ */
+endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify);
+
+#endif /** ENDPOINT_NOTIFY_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
new file mode 100644
index 000000000..4158c3e07
--- /dev/null
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "id_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+
+typedef struct private_id_payload_t private_id_payload_t;
+
+/**
+ * Private data of an id_payload_t object.
+ *
+ */
+struct private_id_payload_t {
+ /**
+ * Public id_payload_t interface.
+ */
+ id_payload_t public;
+
+ /**
+ * one of ID_INITIATOR, ID_RESPONDER
+ */
+ payload_type_t payload_type;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Type of the ID Data.
+ */
+ u_int8_t id_type;
+
+ /**
+ * The contained id data value.
+ */
+ chunk_t id_data;
+};
+
+/**
+ * Encoding rules to parse or generate a ID payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_id_payload_t.
+ *
+ */
+encoding_rule_t id_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_id_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_id_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
+ /* 1 Byte ID type*/
+ { U_INT_8, offsetof(private_id_payload_t, id_type) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some id data bytes, length is defined in PAYLOAD_LENGTH */
+ { ID_DATA, offsetof(private_id_payload_t, id_data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ID Type ! RESERVED |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Identification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_id_payload_t *this)
+{
+ if ((this->id_type == 0) ||
+ (this->id_type == 4) ||
+ ((this->id_type >= 6) && (this->id_type <= 8)) ||
+ ((this->id_type >= 12) && (this->id_type <= 200)))
+ {
+ /* reserved IDs */
+ DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of id_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = id_payload_encodings;
+ *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_id_payload_t *this)
+{
+ return this->payload_type;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_id_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_id_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_id_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of id_payload_t.set_type.
+ */
+static void set_id_type (private_id_payload_t *this, id_type_t type)
+{
+ this->id_type = type;
+}
+
+/**
+ * Implementation of id_payload_t.get_id_type.
+ */
+static id_type_t get_id_type (private_id_payload_t *this)
+{
+ return (this->id_type);
+}
+
+/**
+ * Implementation of id_payload_t.set_data.
+ */
+static void set_data (private_id_payload_t *this, chunk_t data)
+{
+ if (this->id_data.ptr != NULL)
+ {
+ chunk_free(&(this->id_data));
+ }
+ this->id_data.ptr = clalloc(data.ptr,data.len);
+ this->id_data.len = data.len;
+ this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len;
+}
+
+
+/**
+ * Implementation of id_payload_t.get_data_clone.
+ */
+static chunk_t get_data (private_id_payload_t *this)
+{
+ return (this->id_data);
+}
+
+/**
+ * Implementation of id_payload_t.get_data_clone.
+ */
+static chunk_t get_data_clone (private_id_payload_t *this)
+{
+ chunk_t cloned_data;
+ if (this->id_data.ptr == NULL)
+ {
+ return (this->id_data);
+ }
+ cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len);
+ cloned_data.len = this->id_data.len;
+ return cloned_data;
+}
+
+/**
+ * Implementation of id_payload_t.get_identification.
+ */
+static identification_t *get_identification (private_id_payload_t *this)
+{
+ return identification_create_from_encoding(this->id_type,this->id_data);
+}
+
+/**
+ * Implementation of payload_t.destroy and id_payload_t.destroy.
+ */
+static void destroy(private_id_payload_t *this)
+{
+ if (this->id_data.ptr != NULL)
+ {
+ chunk_free(&(this->id_data));
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+id_payload_t *id_payload_create(payload_type_t payload_type)
+{
+ private_id_payload_t *this = malloc_thing(private_id_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (id_payload_t *)) destroy;
+ this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type;
+ this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type;
+ this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data;
+ this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data;
+ this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone;
+
+ this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =ID_PAYLOAD_HEADER_LENGTH;
+ this->id_data = chunk_empty;
+ this->payload_type = payload_type;
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header.
+ */
+id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, identification_t *identification)
+{
+ id_payload_t *this= id_payload_create(payload_type);
+ this->set_data(this,identification->get_encoding(identification));
+ this->set_id_type(this,identification->get_type(identification));
+ return this;
+}
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
new file mode 100644
index 000000000..5502dc961
--- /dev/null
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup id_payload id_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef ID_PAYLOAD_H_
+#define ID_PAYLOAD_H_
+
+typedef struct id_payload_t id_payload_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a id payload without the data in bytes.
+ */
+#define ID_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Object representing an IKEv2 ID payload.
+ *
+ * The ID payload format is described in RFC section 3.5.
+ */
+struct id_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the ID type.
+ *
+ * @param type Type of ID
+ */
+ void (*set_id_type) (id_payload_t *this, id_type_t type);
+
+ /**
+ * Get the ID type.
+ *
+ * @return type of the ID
+ */
+ id_type_t (*get_id_type) (id_payload_t *this);
+
+ /**
+ * Set the ID data.
+ *
+ * Data are getting cloned.
+ *
+ * @param data ID data as chunk_t
+ */
+ void (*set_data) (id_payload_t *this, chunk_t data);
+
+ /**
+ * Get the ID data.
+ *
+ * Returned data are a copy of the internal one
+ *
+ * @return ID data as chunk_t
+ */
+ chunk_t (*get_data_clone) (id_payload_t *this);
+
+ /**
+ * Get the ID data.
+ *
+ * Returned data are NOT copied.
+ *
+ * @return ID data as chunk_t
+ */
+ chunk_t (*get_data) (id_payload_t *this);
+
+ /**
+ * Creates an identification object of this id payload.
+ *
+ * Returned object has to get destroyed by the caller.
+ *
+ * @return identification_t object
+ */
+ identification_t *(*get_identification) (id_payload_t *this);
+
+ /**
+ * Destroys an id_payload_t object.
+ */
+ void (*destroy) (id_payload_t *this);
+};
+
+/**
+ * Creates an empty id_payload_t object.
+ *
+ * @param payload_type one of ID_INITIATOR, ID_RESPONDER
+ * @return id_payload_t object
+ */
+id_payload_t *id_payload_create(payload_type_t payload_type);
+
+/**
+ * Creates an id_payload_t from an existing identification_t object.
+ *
+ * @param payload_type one of ID_INITIATOR, ID_RESPONDER
+ * @param identification identification_t object
+ * @return id_payload_t object
+ */
+id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
+ identification_t *identification);
+
+#endif /** ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
new file mode 100644
index 000000000..735f01304
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "ike_header.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_ike_header_t private_ike_header_t;
+
+/**
+ * Private data of an ike_header_t object.
+ */
+struct private_ike_header_t {
+ /**
+ * Public interface.
+ */
+ ike_header_t public;
+
+ /**
+ * SPI of the initiator.
+ */
+ u_int64_t initiator_spi;
+
+ /**
+ * SPI of the responder.
+ */
+ u_int64_t responder_spi;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+ /**
+ * IKE major version.
+ */
+ u_int8_t maj_version;
+
+ /**
+ * IKE minor version.
+ */
+ u_int8_t min_version;
+
+ /**
+ * Exchange type .
+ */
+ u_int8_t exchange_type;
+
+ /**
+ * Flags of the Message.
+ */
+ struct {
+ /**
+ * Sender is initiator of the associated IKE_SA_INIT-Exchange.
+ */
+ bool initiator;
+
+ /**
+ * Is protocol supporting higher version?
+ */
+ bool version;
+
+ /**
+ * TRUE, if this is a response, FALSE if its a Request.
+ */
+ bool response;
+ } flags;
+
+ /**
+ * Associated Message-ID.
+ */
+ u_int32_t message_id;
+
+ /**
+ * Length of the whole IKEv2-Message (header and all payloads).
+ */
+ u_int32_t length;
+};
+
+ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
+ "EXCHANGE_TYPE_UNDEFINED");
+ENUM_NEXT(exchange_type_names, IKE_SA_INIT, INFORMATIONAL, EXCHANGE_TYPE_UNDEFINED,
+ "IKE_SA_INIT",
+ "IKE_AUTH",
+ "CREATE_CHILD_SA",
+ "INFORMATIONAL");
+#ifdef ME
+ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, INFORMATIONAL,
+ "ME_CONNECT");
+ENUM_END(exchange_type_names, ME_CONNECT);
+#else
+ENUM_END(exchange_type_names, INFORMATIONAL);
+#endif /* ME */
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Header.
+ *
+ * The defined offsets are the positions in a object of type
+ * ike_header_t.
+ */
+encoding_rule_t ike_header_encodings[] = {
+ /* 8 Byte SPI, stored in the field initiator_spi */
+ { IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
+ /* 8 Byte SPI, stored in the field responder_spi */
+ { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ike_header_t, next_payload) },
+ /* 4 Bit major version, stored in the field maj_version */
+ { U_INT_4, offsetof(private_ike_header_t, maj_version) },
+ /* 4 Bit minor version, stored in the field min_version */
+ { U_INT_4, offsetof(private_ike_header_t, min_version) },
+ /* 8 Bit for the exchange type */
+ { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
+ /* 2 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* 3 Bit flags, stored in the fields response, version and initiator */
+ { FLAG, offsetof(private_ike_header_t, flags.response) },
+ { FLAG, offsetof(private_ike_header_t, flags.version) },
+ { FLAG, offsetof(private_ike_header_t, flags.initiator) },
+ /* 3 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* 4 Byte message id, stored in the field message_id */
+ { U_INT_32, offsetof(private_ike_header_t, message_id) },
+ /* 4 Byte length fied, stored in the field length */
+ { HEADER_LENGTH, offsetof(private_ike_header_t, length) }
+};
+
+
+/* 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IKE_SA Initiator's SPI !
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! IKE_SA Responder's SPI !
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Message ID !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ike_header_t *this)
+{
+ if ((this->exchange_type < IKE_SA_INIT) ||
+ ((this->exchange_type > INFORMATIONAL)
+#ifdef ME
+ && (this->exchange_type != ME_CONNECT)
+#endif /* ME */
+ ))
+ {
+ /* unsupported exchange type */
+ return FAILED;
+ }
+
+ if (this->initiator_spi == 0
+#ifdef ME
+ /* we allow zero spi for INFORMATIONAL exchanges,
+ * to allow connectivity checks */
+ && this->exchange_type != INFORMATIONAL
+#endif /* ME */
+ )
+ {
+ /* initiator spi not set */
+ return FAILED;
+ }
+
+ /* verification of version is not done in here */
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(payload_t *this,payload_type_t type)
+{
+ ((private_ike_header_t *)this)->next_payload = type;
+}
+/**
+ * Implementation of ike_header_t.get_initiator_spi.
+ */
+static u_int64_t get_initiator_spi(private_ike_header_t *this)
+{
+ return this->initiator_spi;
+}
+
+/**
+ * Implementation of ike_header_t.set_initiator_spi.
+ */
+static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
+{
+ this->initiator_spi = initiator_spi;
+}
+
+/**
+ * Implementation of ike_header_t.get_responder_spi.
+ */
+static u_int64_t get_responder_spi(private_ike_header_t *this)
+{
+ return this->responder_spi;
+}
+
+/**
+ * Implementation of ike_header_t.set_responder_spi.
+ */
+static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
+{
+ this->responder_spi = responder_spi;
+}
+
+/**
+ * Implementation of ike_header_t.get_maj_version.
+ */
+static u_int8_t get_maj_version(private_ike_header_t *this)
+{
+ return this->maj_version;
+}
+
+/**
+ * Implementation of ike_header_t.get_min_version.
+ */
+static u_int8_t get_min_version(private_ike_header_t *this)
+{
+ return this->min_version;
+}
+
+/**
+ * Implementation of ike_header_t.get_response_flag.
+ */
+static bool get_response_flag(private_ike_header_t *this)
+{
+ return this->flags.response;
+}
+
+/**
+ * Implementation of ike_header_t.set_response_flag.
+ */
+static void set_response_flag(private_ike_header_t *this, bool response)
+{
+ this->flags.response = response;
+}
+
+/**
+ * Implementation of ike_header_t.get_version_flag.
+ */
+static bool get_version_flag(private_ike_header_t *this)
+{
+ return this->flags.version;
+}
+
+/**
+ * Implementation of ike_header_t.get_initiator_flag.
+ */
+static bool get_initiator_flag(private_ike_header_t *this)
+{
+ return this->flags.initiator;
+}
+
+/**
+ * Implementation of ike_header_t.set_initiator_flag.
+ */
+static void set_initiator_flag(private_ike_header_t *this, bool initiator)
+{
+ this->flags.initiator = initiator;
+}
+
+/**
+ * Implementation of ike_header_t.get_exchange_type.
+ */
+static u_int8_t get_exchange_type(private_ike_header_t *this)
+{
+ return this->exchange_type;
+}
+
+/**
+ * Implementation of ike_header_t.set_exchange_type.
+ */
+static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
+{
+ this->exchange_type = exchange_type;
+}
+
+/**
+ * Implements ike_header_t's get_message_id function.
+ * See #ike_header_t.get_message_id for description.
+ */
+static u_int32_t get_message_id(private_ike_header_t *this)
+{
+ return this->message_id;
+}
+
+/**
+ * Implementation of ike_header_t.set_message_id.
+ */
+static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
+{
+ this->message_id = message_id;
+}
+
+/**
+ * Implementation of ike_header_t.destroy and payload_t.destroy.
+ */
+static void destroy(ike_header_t *this)
+{
+ free(this);
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ike_header_encodings;
+ *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(payload_t *this)
+{
+ return HEADER;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(payload_t *this)
+{
+ return (((private_ike_header_t*)this)->next_payload);
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(payload_t *this)
+{
+ return (((private_ike_header_t*)this)->length);
+}
+
+/*
+ * Described in header.
+ */
+ike_header_t *ike_header_create()
+{
+ private_ike_header_t *this = malloc_thing(private_ike_header_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = get_encoding_rules;
+ this->public.payload_interface.get_length = get_length;
+ this->public.payload_interface.get_next_type = get_next_type;
+ this->public.payload_interface.set_next_type = set_next_type;
+ this->public.payload_interface.get_type = get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+ this->public.destroy = destroy;
+
+ this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
+ this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
+ this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
+ this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
+ this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
+ this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
+ this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
+ this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
+ this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
+ this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
+ this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
+ this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
+ this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
+ this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
+ this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
+
+ /* set default values of the fields */
+ this->initiator_spi = 0;
+ this->responder_spi = 0;
+ this->next_payload = 0;
+ this->maj_version = IKE_MAJOR_VERSION;
+ this->min_version = IKE_MINOR_VERSION;
+ this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
+ this->flags.initiator = TRUE;
+ this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
+ this->flags.response = FALSE;
+ this->message_id = 0;
+ this->length = IKE_HEADER_LENGTH;
+
+ return (ike_header_t*)this;
+}
diff --git a/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h
new file mode 100644
index 000000000..e63e8bf06
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ike_header.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_header ike_header
+ * @{ @ingroup payloads
+ */
+
+#ifndef IKE_HEADER_H_
+#define IKE_HEADER_H_
+
+typedef enum exchange_type_t exchange_type_t;
+typedef struct ike_header_t ike_header_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Major Version of IKEv2.
+ */
+#define IKE_MAJOR_VERSION 2
+
+/**
+ * Minor Version of IKEv2.
+ */
+#define IKE_MINOR_VERSION 0
+
+/**
+ * Flag in IKEv2-Header. Always 0.
+ */
+#define HIGHER_VERSION_SUPPORTED_FLAG 0
+
+/**
+ * Length of IKE Header in Bytes.
+ */
+#define IKE_HEADER_LENGTH 28
+
+/**
+ * Different types of IKE-Exchanges.
+ *
+ * See RFC for different types.
+ */
+enum exchange_type_t{
+
+ /**
+ * EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
+ */
+ EXCHANGE_TYPE_UNDEFINED = 255,
+
+ /**
+ * IKE_SA_INIT.
+ */
+ IKE_SA_INIT = 34,
+
+ /**
+ * IKE_AUTH.
+ */
+ IKE_AUTH = 35,
+
+ /**
+ * CREATE_CHILD_SA.
+ */
+ CREATE_CHILD_SA = 36,
+
+ /**
+ * INFORMATIONAL.
+ */
+ INFORMATIONAL = 37,
+#ifdef ME
+ /**
+ * ME_CONNECT
+ */
+ ME_CONNECT = 240
+#endif /* ME */
+};
+
+/**
+ * enum name for exchange_type_t
+ */
+extern enum_name_t *exchange_type_names;
+
+/**
+ * An object of this type represents an IKEv2 header and is used to
+ * generate and parse IKEv2 headers.
+ *
+ * The header format of an IKEv2-Message is compatible to the
+ * ISAKMP-Header format to allow implementations supporting
+ * both versions of the IKE-protocol.
+ */
+struct ike_header_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the initiator spi.
+ *
+ * @return initiator_spi
+ */
+ u_int64_t (*get_initiator_spi) (ike_header_t *this);
+
+ /**
+ * Set the initiator spi.
+ *
+ * @param initiator_spi initiator_spi
+ */
+ void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
+
+ /**
+ * Get the responder spi.
+ *
+ * @return responder_spi
+ */
+ u_int64_t (*get_responder_spi) (ike_header_t *this);
+
+ /**
+ * Set the responder spi.
+ *
+ * @param responder_spi responder_spi
+ */
+ void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
+
+ /**
+ * Get the major version.
+ *
+ * @return major version
+ */
+ u_int8_t (*get_maj_version) (ike_header_t *this);
+
+ /**
+ * Get the minor version.
+ *
+ * @return minor version
+ */
+ u_int8_t (*get_min_version) (ike_header_t *this);
+
+ /**
+ * Get the response flag.
+ *
+ * @return response flag
+ */
+ bool (*get_response_flag) (ike_header_t *this);
+
+ /**
+ * Set the response flag-
+ *
+ * @param response response flag
+ */
+ void (*set_response_flag) (ike_header_t *this, bool response);
+ /**
+ * Get "higher version supported"-flag.
+ *
+ * @return version flag
+ */
+ bool (*get_version_flag) (ike_header_t *this);
+
+ /**
+ * Get the initiator flag.
+ *
+ * @return initiator flag
+ */
+ bool (*get_initiator_flag) (ike_header_t *this);
+
+ /**
+ * Set the initiator flag.
+ *
+ * @param initiator initiator flag
+ */
+ void (*set_initiator_flag) (ike_header_t *this, bool initiator);
+
+ /**
+ * Get the exchange type.
+ *
+ * @return exchange type
+ */
+ u_int8_t (*get_exchange_type) (ike_header_t *this);
+
+ /**
+ * Set the exchange type.
+ *
+ * @param exchange_type exchange type
+ */
+ void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
+
+ /**
+ * Get the message id.
+ *
+ * @return message id
+ */
+ u_int32_t (*get_message_id) (ike_header_t *this);
+
+ /**
+ * Set the message id.
+ *
+ * @param initiator_spi message id
+ */
+ void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
+
+ /**
+ * Destroys a ike_header_t object.
+ */
+ void (*destroy) (ike_header_t *this);
+};
+
+/**
+ * Create an ike_header_t object
+ *
+ * @return ike_header_t object
+ */
+ike_header_t *ike_header_create(void);
+
+#endif /** IKE_HEADER_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
new file mode 100644
index 000000000..1bc79f084
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "ke_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_ke_payload_t private_ke_payload_t;
+
+/**
+ * Private data of an ke_payload_t object.
+ *
+ */
+struct private_ke_payload_t {
+ /**
+ * Public ke_payload_t interface.
+ */
+ ke_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * DH Group Number.
+ */
+ u_int16_t dh_group_number;
+
+ /**
+ * Key Exchange Data of this KE payload.
+ */
+ chunk_t key_exchange_data;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-KE Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_ke_payload_t.
+ *
+ */
+encoding_rule_t ke_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_ke_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
+ /* DH Group number as 16 bit field*/
+ { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* Key Exchange Data is from variable size */
+ { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! DH Group # ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Key Exchange Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ke_payload_t *this)
+{
+ /* dh group is not verified in here */
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.destroy.
+ */
+static void destroy(private_ke_payload_t *this)
+{
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ free(this->key_exchange_data.ptr);
+ }
+ free(this);
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ke_payload_encodings;
+ *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_ke_payload_t *this)
+{
+ return KEY_EXCHANGE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_ke_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_ke_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_ke_payload_t *this)
+{
+ size_t length = KE_PAYLOAD_HEADER_LENGTH;
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ length += this->key_exchange_data.len;
+ }
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_ke_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of ke_payload_t.get_key_exchange_data.
+ */
+static chunk_t get_key_exchange_data(private_ke_payload_t *this)
+{
+ return (this->key_exchange_data);
+}
+
+/**
+ * Implementation of ke_payload_t.set_key_exchange_data.
+ */
+static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
+{
+ /* destroy existing data first */
+ if (this->key_exchange_data.ptr != NULL)
+ {
+ /* free existing value */
+ free(this->key_exchange_data.ptr);
+ this->key_exchange_data.ptr = NULL;
+ this->key_exchange_data.len = 0;
+
+ }
+
+ this->key_exchange_data = chunk_clone(key_exchange_data);
+ compute_length(this);
+}
+
+/**
+ * Implementation of ke_payload_t.get_dh_group_number.
+ */
+static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
+{
+ return this->dh_group_number;
+}
+
+/**
+ * Implementation of ke_payload_t.set_dh_group_number.
+ */
+static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
+{
+ this->dh_group_number = dh_group_number;
+}
+
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create()
+{
+ private_ke_payload_t *this = malloc_thing(private_ke_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
+ this->public.set_key_exchange_data = (void (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
+ this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
+ this->public.set_dh_group_number =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
+ this->public.destroy = (void (*) (ke_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
+ this->key_exchange_data = chunk_empty;
+ this->dh_group_number = MODP_NONE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
+{
+ private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
+
+ dh->get_my_public_value(dh, &this->key_exchange_data);
+ this->dh_group_number = dh->get_dh_group(dh);
+ compute_length(this);
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
new file mode 100644
index 000000000..3ca05009e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ke_payload ke_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef KE_PAYLOAD_H_
+#define KE_PAYLOAD_H_
+
+typedef struct ke_payload_t ke_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <utils/linked_list.h>
+#include <crypto/diffie_hellman.h>
+
+/**
+ * KE payload length in bytes without any key exchange data.
+ */
+#define KE_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2-KE Payload.
+ *
+ * The KE Payload format is described in RFC section 3.4.
+ */
+struct ke_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Returns the currently set key exchange data of this KE payload.
+ *
+ * @warning Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_key_exchange_data) (ke_payload_t *this);
+
+ /**
+ * Sets the key exchange data of this KE payload.
+ *
+ * Value is getting copied.
+ *
+ * @param key_exchange_data chunk_t pointing to the value to set
+ */
+ void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
+
+ /**
+ * Gets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @return DH Group Number of this payload
+ */
+ diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
+
+ /**
+ * Sets the Diffie-Hellman Group Number of this KE payload.
+ *
+ * @param dh_group_number DH Group to set
+ */
+ void (*set_dh_group_number) (ke_payload_t *this,
+ diffie_hellman_group_t dh_group_number);
+
+ /**
+ * Destroys an ke_payload_t object.
+ */
+ void (*destroy) (ke_payload_t *this);
+};
+
+/**
+ * Creates an empty ke_payload_t object
+ *
+ * @return ke_payload_t object
+ */
+ke_payload_t *ke_payload_create(void);
+
+/**
+ * Creates a ke_payload_t from a diffie_hellman_t
+ *
+ * @param diffie_hellman diffie hellman object containing group and key
+ * @return ke_payload_t object
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(
+ diffie_hellman_t *diffie_hellman);
+
+#endif /** KE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c
new file mode 100644
index 000000000..4ad5ce9dd
--- /dev/null
+++ b/src/libcharon/encoding/payloads/nonce_payload.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* offsetof macro */
+#include <stddef.h>
+
+#include "nonce_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+
+typedef struct private_nonce_payload_t private_nonce_payload_t;
+
+/**
+ * Private data of an nonce_payload_t object.
+ *
+ */
+struct private_nonce_payload_t {
+ /**
+ * Public nonce_payload_t interface.
+ */
+ nonce_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * The contained nonce value.
+ */
+ chunk_t nonce;
+};
+
+/**
+ * Encoding rules to parse or generate a nonce payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_nonce_payload_t.
+ *
+ */
+encoding_rule_t nonce_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_nonce_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole nonce payload*/
+ { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
+ /* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
+ { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }
+};
+
+/* 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Nonce Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_nonce_payload_t *this)
+{
+ if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
+ {
+ /* nonce length is wrong */
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of nonce_payload_t.set_nonce.
+ */
+static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
+{
+ this->nonce.ptr = clalloc(nonce.ptr, nonce.len);
+ this->nonce.len = nonce.len;
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of nonce_payload_t.get_nonce.
+ */
+static chunk_t get_nonce(private_nonce_payload_t *this)
+{
+ chunk_t nonce;
+ nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len);
+ nonce.len = this->nonce.len;
+ return nonce;
+}
+
+/**
+ * Implementation of nonce_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = nonce_payload_encodings;
+ *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_nonce_payload_t *this)
+{
+ return NONCE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_nonce_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_nonce_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_nonce_payload_t *this)
+{
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_nonce_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of payload_t.destroy and nonce_payload_t.destroy.
+ */
+static void destroy(private_nonce_payload_t *this)
+{
+ if (this->nonce.ptr != NULL)
+ {
+ free(this->nonce.ptr);
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+nonce_payload_t *nonce_payload_create()
+{
+ private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (nonce_payload_t *)) destroy;
+ this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce;
+ this->public.get_nonce = (chunk_t (*) (nonce_payload_t *)) get_nonce;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
+ this->nonce.ptr = NULL;
+ this->nonce.len = 0;
+
+ return (&(this->public));
+}
+
+
diff --git a/src/libcharon/encoding/payloads/nonce_payload.h b/src/libcharon/encoding/payloads/nonce_payload.h
new file mode 100644
index 000000000..e9212202e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/nonce_payload.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup nonce_payload nonce_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef NONCE_PAYLOAD_H_
+#define NONCE_PAYLOAD_H_
+
+typedef struct nonce_payload_t nonce_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Nonce size in bytes for nonces sending to other peer.
+ */
+#define NONCE_SIZE 32
+
+/**
+ * Length of a nonce payload without a nonce in bytes.
+ */
+#define NONCE_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Object representing an IKEv2 Nonce payload.
+ *
+ * The Nonce payload format is described in RFC section 3.3.
+ */
+struct nonce_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the nonce value.
+ *
+ * @param nonce chunk containing the nonce, will be cloned
+ */
+ void (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
+
+ /**
+ * Get the nonce value.
+ *
+ * @return a chunk containing the cloned nonce
+ */
+ chunk_t (*get_nonce) (nonce_payload_t *this);
+
+ /**
+ * Destroys an nonce_payload_t object.
+ */
+ void (*destroy) (nonce_payload_t *this);
+};
+
+/**
+ * Creates an empty nonce_payload_t object
+ *
+ * @return nonce_payload_t object
+ */
+nonce_payload_t *nonce_payload_create(void);
+
+#endif /** NONCE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
new file mode 100644
index 000000000..469698ef5
--- /dev/null
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "notify_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+#include <crypto/hashers/hasher.h>
+
+ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "UNSUPPORTED_CRITICAL_PAYLOAD");
+ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "INVALID_IKE_SPI",
+ "INVALID_MAJOR_VERSION");
+ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
+ "INVALID_SYNTAX");
+ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
+ "INVALID_MESSAGE_ID");
+ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
+ "INVALID_SPI");
+ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "NO_PROPOSAL_CHOSEN");
+ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
+ "INVALID_KE_PAYLOAD");
+ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ "AUTHENTICATION_FAILED");
+ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, USE_ASSIGNED_HoA, AUTHENTICATION_FAILED,
+ "SINGLE_PAIR_REQUIRED",
+ "NO_ADDITIONAL_SAS",
+ "INTERNAL_ADDRESS_FAILURE",
+ "FAILED_CP_REQUIRED",
+ "TS_UNACCEPTABLE",
+ "INVALID_SELECTORS",
+ "UNACCEPTABLE_ADDRESSES",
+ "UNEXPECTED_NAT_DETECTED",
+ "USE_ASSIGNED_HoA");
+ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, USE_ASSIGNED_HoA,
+ "ME_CONNECT_FAILED");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, LINK_ID, ME_CONNECT_FAILED,
+ "INITIAL_CONTACT",
+ "SET_WINDOW_SIZE",
+ "ADDITIONAL_TS_POSSIBLE",
+ "IPCOMP_SUPPORTED",
+ "NAT_DETECTION_SOURCE_IP",
+ "NAT_DETECTION_DESTINATION_IP",
+ "COOKIE",
+ "USE_TRANSPORT_MODE",
+ "HTTP_CERT_LOOKUP_SUPPORTED",
+ "REKEY_SA",
+ "ESP_TFC_PADDING_NOT_SUPPORTED",
+ "NON_FIRST_FRAGMENTS_ALSO",
+ "MOBIKE_SUPPORTED",
+ "ADDITIONAL_IP4_ADDRESS",
+ "ADDITIONAL_IP6_ADDRESS",
+ "NO_ADDITIONAL_ADDRESSES",
+ "UPDATE_SA_ADDRESSES",
+ "COOKIE2",
+ "NO_NATS_ALLOWED",
+ "AUTH_LIFETIME",
+ "MULTIPLE_AUTH_SUPPORTED",
+ "ANOTHER_AUTH_FOLLOWS",
+ "REDIRECT_SUPPORTED",
+ "REDIRECT",
+ "REDIRECTED_FROM",
+ "TICKET_LT_OPAQUE",
+ "TICKET_REQUEST",
+ "TICKET_ACK",
+ "TICKET_NACK",
+ "TICKET_OPAQUE",
+ "LINK_ID");
+ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, LINK_ID,
+ "EAP_ONLY_AUTHENTICATION");
+ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
+ "USE_BEET_MODE");
+ENUM_NEXT(notify_type_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
+ "ME_MEDIATION",
+ "ME_ENDPOINT",
+ "ME_CALLBACK",
+ "ME_CONNECTID",
+ "ME_CONNECTKEY",
+ "ME_CONNECTAUTH",
+ "ME_RESPONSE");
+ENUM_END(notify_type_names, ME_RESPONSE);
+
+
+ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "CRIT");
+ENUM_NEXT(notify_type_short_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
+ "INVAL_IKE_SPI",
+ "INVAL_MAJOR");
+ENUM_NEXT(notify_type_short_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
+ "INVAL_SYN");
+ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
+ "INVAL_MID");
+ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
+ "INVAL_SPI");
+ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "NO_PROP");
+ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
+ "INVAL_KE");
+ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ "AUTH_FAILED");
+ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, USE_ASSIGNED_HoA, AUTHENTICATION_FAILED,
+ "SINGLE_PAIR",
+ "NO_ADD_SAS",
+ "INT_ADDR_FAIL",
+ "FAIL_CP_REQ",
+ "TS_UNACCEPT",
+ "INVAL_SEL",
+ "UNACCEPT_ADDR",
+ "UNEXPECT_NAT",
+ "ASSIGNED_HoA");
+ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, USE_ASSIGNED_HoA,
+ "ME_CONN_FAIL");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, LINK_ID, ME_CONNECT_FAILED,
+ "INIT_CONTACT",
+ "SET_WINSIZE",
+ "ADD_TS_POSS",
+ "IPCOMP_SUPP",
+ "NATD_S_IP",
+ "NATD_D_IP",
+ "COOKIE",
+ "USE_TRANSP",
+ "HTTP_CERT_LOOK",
+ "REKEY_SA",
+ "ESP_TFC_PAD_N",
+ "NON_FIRST_FRAG",
+ "MOBIKE_SUP",
+ "ADD_4_ADDR",
+ "ADD_6_ADDR",
+ "NO_ADD_ADDR",
+ "UPD_SA_ADDR",
+ "COOKIE2",
+ "NO_NATS",
+ "AUTH_LFT",
+ "MULT_AUTH",
+ "AUTH_FOLLOWS",
+ "REDIR_SUP",
+ "REDIR",
+ "REDIR_FROM",
+ "TKT_LT_OPAK",
+ "TKT_REQ",
+ "TKT_ACK",
+ "TKT_NACK",
+ "TKT_OPAK",
+ "LINK_ID");
+ENUM_NEXT(notify_type_short_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, LINK_ID,
+ "EAP_ONLY");
+ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
+ "BEET_MODE");
+ENUM_NEXT(notify_type_short_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
+ "ME_MED",
+ "ME_EP",
+ "ME_CB",
+ "ME_CID",
+ "ME_CKEY",
+ "ME_CAUTH",
+ "ME_R");
+ENUM_END(notify_type_short_names, ME_RESPONSE);
+
+
+typedef struct private_notify_payload_t private_notify_payload_t;
+
+/**
+ * Private data of an notify_payload_t object.
+ *
+ */
+struct private_notify_payload_t {
+ /**
+ * Public notify_payload_t interface.
+ */
+ notify_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Protocol id.
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * Spi size.
+ */
+ u_int8_t spi_size;
+
+ /**
+ * Notify message type.
+ */
+ u_int16_t notify_type;
+
+ /**
+ * Security parameter index (spi).
+ */
+ chunk_t spi;
+
+ /**
+ * Notification data.
+ */
+ chunk_t notification_data;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Notify Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_notify_payload_t.
+ *
+ */
+encoding_rule_t notify_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_notify_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
+ /* Protocol ID as 8 bit field*/
+ { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
+ /* SPI Size as 8 bit field*/
+ { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
+ /* Notify message type as 16 bit field*/
+ { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
+ /* SPI as variable length field*/
+ { SPI, offsetof(private_notify_payload_t, spi) },
+ /* Key Exchange Data is from variable size */
+ { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Protocol ID ! SPI Size ! Notify Message Type !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Notification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_notify_payload_t *this)
+{
+ bool bad_length = FALSE;
+
+ switch (this->protocol_id)
+ {
+ case PROTO_NONE:
+ case PROTO_IKE:
+ case PROTO_AH:
+ case PROTO_ESP:
+ break;
+ default:
+ DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
+ return FAILED;
+ }
+
+ switch (this->notify_type)
+ {
+ case INVALID_KE_PAYLOAD:
+ {
+ if (this->notification_data.len != 2)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ case ME_CONNECTAUTH:
+ {
+ if (this->notification_data.len != HASH_SIZE_SHA1)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case INVALID_SYNTAX:
+ case INVALID_MAJOR_VERSION:
+ case NO_PROPOSAL_CHOSEN:
+ {
+ if (this->notification_data.len != 0)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ADDITIONAL_IP4_ADDRESS:
+ {
+ if (this->notification_data.len != 4)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ADDITIONAL_IP6_ADDRESS:
+ {
+ if (this->notification_data.len != 16)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case AUTH_LIFETIME:
+ {
+ if (this->notification_data.len != 4)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case IPCOMP_SUPPORTED:
+ {
+ if (this->notification_data.len != 3)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
+ case ME_ENDPOINT:
+ if (this->notification_data.len != 8 &&
+ this->notification_data.len != 12 &&
+ this->notification_data.len != 24)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ case ME_CONNECTID:
+ if (this->notification_data.len < 4 ||
+ this->notification_data.len > 16)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ case ME_CONNECTKEY:
+ if (this->notification_data.len < 16 ||
+ this->notification_data.len > 32)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ default:
+ /* TODO: verify */
+ break;
+ }
+ if (bad_length)
+ {
+ DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
+ notify_type_names, this->notify_type,
+ this->notification_data.len);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = notify_payload_encodings;
+ *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_notify_payload_t *this)
+{
+ return NOTIFY;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_notify_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_notify_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the payloads length.
+ */
+static void compute_length (private_notify_payload_t *this)
+{
+ size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
+ if (this->notification_data.ptr != NULL)
+ {
+ length += this->notification_data.len;
+ }
+ if (this->spi.ptr != NULL)
+ {
+ length += this->spi.len;
+ }
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_notify_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of notify_payload_t.get_protocol_id.
+ */
+static u_int8_t get_protocol_id(private_notify_payload_t *this)
+{
+ return this->protocol_id;
+}
+
+/**
+ * Implementation of notify_payload_t.set_protocol_id.
+ */
+static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+}
+
+/**
+ * Implementation of notify_payload_t.get_notify_type.
+ */
+static notify_type_t get_notify_type(private_notify_payload_t *this)
+{
+ return this->notify_type;
+}
+
+/**
+ * Implementation of notify_payload_t.set_notify_type.
+ */
+static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
+{
+ this->notify_type = notify_type;
+}
+
+/**
+ * Implementation of notify_payload_t.get_spi.
+ */
+static u_int32_t get_spi(private_notify_payload_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi.len == 4)
+ {
+ return *((u_int32_t*)this->spi.ptr);
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of notify_payload_t.set_spi.
+ */
+static void set_spi(private_notify_payload_t *this, u_int32_t spi)
+{
+ chunk_free(&this->spi);
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ this->spi = chunk_alloc(4);
+ *((u_int32_t*)this->spi.ptr) = spi;
+ break;
+ default:
+ break;
+ }
+ this->spi_size = this->spi.len;
+ compute_length(this);
+}
+
+/**
+ * Implementation of notify_payload_t.get_notification_data.
+ */
+static chunk_t get_notification_data(private_notify_payload_t *this)
+{
+ return (this->notification_data);
+}
+
+/**
+ * Implementation of notify_payload_t.set_notification_data.
+ */
+static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
+{
+ chunk_free(&this->notification_data);
+ if (notification_data.len > 0)
+ {
+ this->notification_data = chunk_clone(notification_data);
+ }
+ compute_length(this);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
+ */
+static status_t destroy(private_notify_payload_t *this)
+{
+ chunk_free(&this->notification_data);
+ chunk_free(&this->spi);
+ free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header
+ */
+notify_payload_t *notify_payload_create()
+{
+ private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
+ this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
+ this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
+ this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
+ this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
+ this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
+ this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
+ this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
+ this->public.destroy = (void (*) (notify_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
+ this->protocol_id = 0;
+ this->notify_type = 0;
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ this->spi_size = 0;
+ this->notification_data.ptr = NULL;
+ this->notification_data.len = 0;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
+{
+ notify_payload_t *notify = notify_payload_create();
+
+ notify->set_notify_type(notify,notify_type);
+ notify->set_protocol_id(notify,protocol_id);
+
+ return notify;
+}
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
new file mode 100644
index 000000000..0e1bc23b8
--- /dev/null
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup notify_payload notify_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef NOTIFY_PAYLOAD_H_
+#define NOTIFY_PAYLOAD_H_
+
+typedef enum notify_type_t notify_type_t;
+typedef struct notify_payload_t notify_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * Notify payload length in bytes without any spi and notification data.
+ */
+#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
+
+/**
+ * Notify message types.
+ *
+ * See IKEv2 RFC 3.10.1.
+ */
+enum notify_type_t {
+ /* notify error messages */
+ UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+ INVALID_IKE_SPI = 4,
+ INVALID_MAJOR_VERSION = 5,
+ INVALID_SYNTAX = 7,
+ INVALID_MESSAGE_ID = 9,
+ INVALID_SPI = 11,
+ NO_PROPOSAL_CHOSEN = 14,
+ INVALID_KE_PAYLOAD = 17,
+ AUTHENTICATION_FAILED = 24,
+ SINGLE_PAIR_REQUIRED = 34,
+ NO_ADDITIONAL_SAS = 35,
+ INTERNAL_ADDRESS_FAILURE = 36,
+ FAILED_CP_REQUIRED = 37,
+ TS_UNACCEPTABLE = 38,
+ INVALID_SELECTORS = 39,
+ /* mobile extension, RFC 4555 */
+ UNACCEPTABLE_ADDRESSES = 40,
+ UNEXPECTED_NAT_DETECTED = 41,
+ /* mobile IPv6 bootstrapping, RFC 5026 */
+ USE_ASSIGNED_HoA = 42,
+
+ /* IKE-ME, private use */
+ ME_CONNECT_FAILED = 8192,
+
+ /* notify status messages */
+ INITIAL_CONTACT = 16384,
+ SET_WINDOW_SIZE = 16385,
+ ADDITIONAL_TS_POSSIBLE = 16386,
+ IPCOMP_SUPPORTED = 16387,
+ NAT_DETECTION_SOURCE_IP = 16388,
+ NAT_DETECTION_DESTINATION_IP = 16389,
+ COOKIE = 16390,
+ USE_TRANSPORT_MODE = 16391,
+ HTTP_CERT_LOOKUP_SUPPORTED = 16392,
+ REKEY_SA = 16393,
+ ESP_TFC_PADDING_NOT_SUPPORTED = 16394,
+ NON_FIRST_FRAGMENTS_ALSO = 16395,
+ /* mobike extension, RFC4555 */
+ MOBIKE_SUPPORTED = 16396,
+ ADDITIONAL_IP4_ADDRESS = 16397,
+ ADDITIONAL_IP6_ADDRESS = 16398,
+ NO_ADDITIONAL_ADDRESSES = 16399,
+ UPDATE_SA_ADDRESSES = 16400,
+ COOKIE2 = 16401,
+ NO_NATS_ALLOWED = 16402,
+ /* repeated authentication extension, RFC4478 */
+ AUTH_LIFETIME = 16403,
+ /* multiple authentication exchanges, RFC 4739 */
+ MULTIPLE_AUTH_SUPPORTED = 16404,
+ ANOTHER_AUTH_FOLLOWS = 16405,
+ /* redirect mechanism, RFC 5685 */
+ REDIRECT_SUPPORTED = 16406,
+ REDIRECT = 16407,
+ REDIRECTED_FROM = 16408,
+ /* draft-ietf-ipsecme-ikev2-resumption, assigned by IANA */
+ TICKET_LT_OPAQUE = 16409,
+ TICKET_REQUEST = 16410,
+ TICKET_ACK = 16411,
+ TICKET_NACK = 16412,
+ TICKET_OPAQUE = 16413,
+ LINK_ID = 16414,
+
+ /* draft-eronen-ipsec-ikev2-eap-auth, not assigned by IANA yet */
+ EAP_ONLY_AUTHENTICATION = 40960,
+ /* BEET mode, not even a draft yet. private use */
+ USE_BEET_MODE = 40961,
+ /* IKE-ME, private use */
+ ME_MEDIATION = 40962,
+ ME_ENDPOINT = 40963,
+ ME_CALLBACK = 40964,
+ ME_CONNECTID = 40965,
+ ME_CONNECTKEY = 40966,
+ ME_CONNECTAUTH = 40967,
+ ME_RESPONSE = 40968
+};
+
+/**
+ * enum name for notify_type_t.
+ */
+extern enum_name_t *notify_type_names;
+
+/**
+ * enum name for notify_type_t (shorter strings).
+ */
+extern enum_name_t *notify_type_short_names;
+
+/**
+ * Class representing an IKEv2-Notify Payload.
+ *
+ * The Notify Payload format is described in Draft section 3.10.
+ */
+struct notify_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Gets the protocol id of this payload.
+ *
+ * @return protocol id of this payload
+ */
+ u_int8_t (*get_protocol_id) (notify_payload_t *this);
+
+ /**
+ * Sets the protocol id of this payload.
+ *
+ * @param protocol_id protocol id to set
+ */
+ void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
+
+ /**
+ * Gets the notify message type of this payload.
+ *
+ * @return notify message type of this payload
+ */
+ notify_type_t (*get_notify_type) (notify_payload_t *this);
+
+ /**
+ * Sets notify message type of this payload.
+ *
+ * @param type notify message type to set
+ */
+ void (*set_notify_type) (notify_payload_t *this, notify_type_t type);
+
+ /**
+ * Returns the currently set spi of this payload.
+ *
+ * This is only valid for notifys with protocol AH|ESP
+ *
+ * @return SPI value
+ */
+ u_int32_t (*get_spi) (notify_payload_t *this);
+
+ /**
+ * Sets the spi of this payload.
+ *
+ * This is only valid for notifys with protocol AH|ESP
+ *
+ * @param spi SPI value
+ */
+ void (*set_spi) (notify_payload_t *this, u_int32_t spi);
+
+ /**
+ * Returns the currently set notification data of payload.
+ *
+ * Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_notification_data) (notify_payload_t *this);
+
+ /**
+ * Sets the notification data of this payload.
+ *
+ * @warning Value is getting copied.
+ *
+ * @param notification_data chunk_t pointing to the value to set
+ */
+ void (*set_notification_data) (notify_payload_t *this,
+ chunk_t notification_data);
+
+ /**
+ * Destroys an notify_payload_t object.
+ */
+ void (*destroy) (notify_payload_t *this);
+};
+
+/**
+ * Creates an empty notify_payload_t object
+ *
+ * @return created notify_payload_t object
+ */
+notify_payload_t *notify_payload_create(void);
+
+/**
+ * Creates an notify_payload_t object of specific type for specific protocol id.
+ *
+ * @param protocol_id protocol id (IKE, AH or ESP)
+ * @param type notify type (see notify_type_t)
+ * @return notify_payload_t object
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(
+ protocol_id_t protocol_id, notify_type_t type);
+
+#endif /** NOTIFY_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
new file mode 100644
index 000000000..1cee6d2aa
--- /dev/null
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "payload.h"
+
+#include <encoding/payloads/ike_header.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
+#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <encoding/payloads/eap_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, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
+ "SECURITY_ASSOCIATION",
+ "KEY_EXCHANGE",
+ "ID_INITIATOR",
+ "ID_RESPONDER",
+ "CERTIFICATE",
+ "CERTIFICATE_REQUEST",
+ "AUTHENTICATION",
+ "NONCE",
+ "NOTIFY",
+ "DELETE",
+ "VENDOR_ID",
+ "TRAFFIC_SELECTOR_INITIATOR",
+ "TRAFFIC_SELECTOR_RESPONDER",
+ "ENCRYPTED",
+ "CONFIGURATION",
+ "EXTENSIBLE_AUTHENTICATION");
+#ifdef ME
+ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ "ID_PEER");
+ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HEADER",
+ "PROPOSAL_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_ATTRIBUTE",
+ "TRAFFIC_SELECTOR_SUBSTRUCTURE",
+ "CONFIGURATION_ATTRIBUTE",
+ "UNKNOWN_PAYLOAD");
+#else
+ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ "HEADER",
+ "PROPOSAL_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_ATTRIBUTE",
+ "TRAFFIC_SELECTOR_SUBSTRUCTURE",
+ "CONFIGURATION_ATTRIBUTE",
+ "UNKNOWN_PAYLOAD");
+#endif /* ME */
+ENUM_END(payload_type_names, UNKNOWN_PAYLOAD);
+
+/* short forms of payload names */
+ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
+ "--");
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
+ "SA",
+ "KE",
+ "IDi",
+ "IDr",
+ "CERT",
+ "CERTREQ",
+ "AUTH",
+ "No",
+ "N",
+ "D",
+ "V",
+ "TSi",
+ "TSr",
+ "E",
+ "CP",
+ "EAP");
+#ifdef ME
+ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
+ "IDp");
+ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HDR",
+ "PROP",
+ "TRANS",
+ "TRANSATTR",
+ "TSSUB",
+ "CPATTR",
+ "??");
+#else
+ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ "HDR",
+ "PROP",
+ "TRANS",
+ "TRANSATTR",
+ "TSSUB",
+ "CPATTR",
+ "??");
+#endif /* ME */
+ENUM_END(payload_type_short_names, UNKNOWN_PAYLOAD);
+
+/*
+ * see header
+ */
+payload_t *payload_create(payload_type_t type)
+{
+ switch (type)
+ {
+ case HEADER:
+ return (payload_t*)ike_header_create();
+ case SECURITY_ASSOCIATION:
+ return (payload_t*)sa_payload_create();
+ case PROPOSAL_SUBSTRUCTURE:
+ return (payload_t*)proposal_substructure_create();
+ case TRANSFORM_SUBSTRUCTURE:
+ return (payload_t*)transform_substructure_create();
+ case TRANSFORM_ATTRIBUTE:
+ return (payload_t*)transform_attribute_create();
+ case NONCE:
+ return (payload_t*)nonce_payload_create();
+ case ID_INITIATOR:
+ return (payload_t*)id_payload_create(ID_INITIATOR);
+ case ID_RESPONDER:
+ return (payload_t*)id_payload_create(ID_RESPONDER);
+#ifdef ME
+ case ID_PEER:
+ return (payload_t*)id_payload_create(ID_PEER);
+#endif /* ME */
+ case AUTHENTICATION:
+ return (payload_t*)auth_payload_create();
+ case CERTIFICATE:
+ return (payload_t*)cert_payload_create();
+ case CERTIFICATE_REQUEST:
+ return (payload_t*)certreq_payload_create();
+ case TRAFFIC_SELECTOR_SUBSTRUCTURE:
+ return (payload_t*)traffic_selector_substructure_create();
+ case TRAFFIC_SELECTOR_INITIATOR:
+ return (payload_t*)ts_payload_create(TRUE);
+ case TRAFFIC_SELECTOR_RESPONDER:
+ return (payload_t*)ts_payload_create(FALSE);
+ case KEY_EXCHANGE:
+ return (payload_t*)ke_payload_create();
+ case NOTIFY:
+ return (payload_t*)notify_payload_create();
+ case DELETE:
+ return (payload_t*)delete_payload_create(0);
+ case VENDOR_ID:
+ return (payload_t*)vendor_id_payload_create();
+ case CONFIGURATION:
+ return (payload_t*)cp_payload_create();
+ case CONFIGURATION_ATTRIBUTE:
+ return (payload_t*)configuration_attribute_create();
+ case EXTENSIBLE_AUTHENTICATION:
+ return (payload_t*)eap_payload_create();
+ case ENCRYPTED:
+ return (payload_t*)encryption_payload_create();
+ default:
+ return (payload_t*)unknown_payload_create();
+ }
+}
+
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
new file mode 100644
index 000000000..2e783cb30
--- /dev/null
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup payload payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef PAYLOAD_H_
+#define PAYLOAD_H_
+
+typedef enum payload_type_t payload_type_t;
+typedef struct payload_t payload_t;
+
+#include <library.h>
+#include <encoding/payloads/encodings.h>
+
+
+/**
+ * Payload-Types of a IKEv2-Message.
+ *
+ * Header and substructures are also defined as
+ * payload types with values from PRIVATE USE space.
+ */
+enum payload_type_t{
+
+ /**
+ * End of payload list in next_payload
+ */
+ NO_PAYLOAD = 0,
+
+ /**
+ * The security association (SA) payload containing proposals.
+ */
+ SECURITY_ASSOCIATION = 33,
+
+ /**
+ * The key exchange (KE) payload containing diffie-hellman values.
+ */
+ KEY_EXCHANGE = 34,
+
+ /**
+ * Identification for the original initiator (IDi).
+ */
+ ID_INITIATOR = 35,
+
+ /**
+ * Identification for the original responder (IDr).
+ */
+ ID_RESPONDER = 36,
+
+ /**
+ * Certificate payload with certificates (CERT).
+ */
+ CERTIFICATE = 37,
+
+ /**
+ * Certificate request payload (CERTREQ).
+ */
+ CERTIFICATE_REQUEST = 38,
+
+ /**
+ * Authentication payload contains auth data (AUTH).
+ */
+ AUTHENTICATION = 39,
+
+ /**
+ * Nonces, for initator and responder (Ni, Nr, N)
+ */
+ NONCE = 40,
+
+ /**
+ * Notify paylaod (N).
+ */
+ NOTIFY = 41,
+
+ /**
+ * Delete payload (D)
+ */
+ DELETE = 42,
+
+ /**
+ * Vendor id paylpoad (V).
+ */
+ VENDOR_ID = 43,
+
+ /**
+ * Traffic selector for the original initiator (TSi).
+ */
+ TRAFFIC_SELECTOR_INITIATOR = 44,
+
+ /**
+ * Traffic selector for the original responser (TSr).
+ */
+ TRAFFIC_SELECTOR_RESPONDER = 45,
+
+ /**
+ * Encryption payload, contains other payloads (E).
+ */
+ ENCRYPTED = 46,
+
+ /**
+ * Configuration payload (CP).
+ */
+ CONFIGURATION = 47,
+
+ /**
+ * Extensible authentication payload (EAP).
+ */
+ EXTENSIBLE_AUTHENTICATION = 48,
+
+#ifdef ME
+ /**
+ * Identification payload for peers has a value from
+ * the PRIVATE USE space.
+ */
+ ID_PEER = 128,
+#endif /* ME */
+
+ /**
+ * Header has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle IKEv2-Header like a payload.
+ */
+ HEADER = 140,
+
+ /**
+ * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a proposal substructure like a payload.
+ */
+ PROPOSAL_SUBSTRUCTURE = 141,
+
+ /**
+ * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform substructure like a payload.
+ */
+ TRANSFORM_SUBSTRUCTURE = 142,
+
+ /**
+ * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform attribute like a payload.
+ */
+ TRANSFORM_ATTRIBUTE = 143,
+
+ /**
+ * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform selector like a payload.
+ */
+ TRAFFIC_SELECTOR_SUBSTRUCTURE = 144,
+
+ /**
+ * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a transform attribute like a payload.
+ */
+ CONFIGURATION_ATTRIBUTE = 145,
+
+ /**
+ * A unknown payload has a value of PRIVATE USE space.
+ *
+ * This payload type is not sent over wire and just
+ * used internally to handle a unknown payload.
+ */
+ UNKNOWN_PAYLOAD = 146,
+};
+
+
+/**
+ * enum names for payload_type_t.
+ */
+extern enum_name_t *payload_type_names;
+
+/**
+ * enum names for payload_type_t in a short form.
+ */
+extern enum_name_t *payload_type_short_names;
+
+/**
+ * Generic interface for all payload types (incl.header and substructures).
+ *
+ * To handle all kinds of payloads on a generic way, this interface must
+ * be implemented by every payload. This allows parser_t/generator_t a simple
+ * handling of all payloads.
+ */
+struct payload_t {
+
+ /**
+ * Get encoding rules for this payload.
+ *
+ * @param rules location to store pointer of first rule
+ * @param rule_count location to store number of rules
+ */
+ void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
+
+ /**
+ * Get type of payload.
+ *
+ * @return type of this payload
+ */
+ payload_type_t (*get_type) (payload_t *this);
+
+ /**
+ * Get type of next payload or NO_PAYLOAD (0) if this is the last one.
+ *
+ * @return type of next payload
+ */
+ payload_type_t (*get_next_type) (payload_t *this);
+
+ /**
+ * Set type of next payload.
+ *
+ * @param type type of next payload
+ */
+ void (*set_next_type) (payload_t *this,payload_type_t type);
+
+ /**
+ * Get length of payload.
+ *
+ * @return length of this payload
+ */
+ size_t (*get_length) (payload_t *this);
+
+ /**
+ * Verifies payload structure and makes consistence check.
+ *
+ * @return SUCCESS, FAILED if consistence not given
+ */
+ status_t (*verify) (payload_t *this);
+
+ /**
+ * Destroys a payload and all included substructures.
+ */
+ void (*destroy) (payload_t *this);
+};
+
+/**
+ * Create an empty payload.
+ *
+ * Useful for the parser, who wants a generic constructor for all payloads.
+ * It supports all payload_t methods. If a payload type is not known,
+ * an unknwon_paylod is created with the chunk of data in it.
+ *
+ * @param type type of the payload to create
+ * @return payload_t object
+ */
+payload_t *payload_create(payload_type_t type);
+
+#endif /** PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
new file mode 100644
index 000000000..c93f73a68
--- /dev/null
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "proposal_substructure.h"
+
+#include <encoding/payloads/encodings.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <library.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+/**
+ * IKEv1 Value for a proposal payload.
+ */
+#define PROPOSAL_TYPE_VALUE 2
+
+
+typedef struct private_proposal_substructure_t private_proposal_substructure_t;
+
+/**
+ * Private data of an proposal_substructure_t object.
+ *
+ */
+struct private_proposal_substructure_t {
+ /**
+ * Public proposal_substructure_t interface.
+ */
+ proposal_substructure_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t proposal_length;
+
+ /**
+ * Proposal number.
+ */
+ u_int8_t proposal_number;
+
+ /**
+ * Protocol ID.
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * SPI size of the following SPI.
+ */
+ u_int8_t spi_size;
+
+ /**
+ * Number of transforms.
+ */
+ u_int8_t transforms_count;
+
+ /**
+ * SPI is stored as chunk.
+ */
+ chunk_t spi;
+
+ /**
+ * Transforms are stored in a linked_list_t.
+ */
+ linked_list_t * transforms;
+};
+
+/**
+ * Encoding rules to parse or generate a Proposal substructure.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_proposal_substructure_t.
+ */
+encoding_rule_t proposal_substructure_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* Length of the whole proposal substructure payload*/
+ { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
+ /* proposal number is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
+ /* protocol ID is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
+ /* SPI Size has its own type */
+ { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
+ /* Number of transforms is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
+ /* SPI is a chunk of variable size*/
+ { SPI, offsetof(private_proposal_substructure_t, spi) },
+ /* Transforms are stored in a transform substructure,
+ offset points to a linked_list_t pointer */
+ { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! 0 (last) or 2 ! RESERVED ! Proposal Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ SPI (variable) ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Transforms> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_proposal_substructure_t *this)
+{
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ payload_t *current_transform;
+
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2))
+ {
+ /* must be 0 or 2 */
+ DBG1(DBG_ENC, "inconsistent next payload");
+ return FAILED;
+ }
+ if (this->transforms_count != this->transforms->get_count(this->transforms))
+ {
+ /* must be the same! */
+ DBG1(DBG_ENC, "transform count invalid");
+ return FAILED;
+ }
+
+ switch (this->protocol_id)
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ if (this->spi.len != 4)
+ {
+ DBG1(DBG_ENC, "invalid SPI length in %N proposal",
+ protocol_id_names, this->protocol_id);
+ return FAILED;
+ }
+ break;
+ case PROTO_IKE:
+ if (this->spi.len != 0 && this->spi.len != 8)
+ {
+ DBG1(DBG_ENC, "invalid SPI length in IKE proposal");
+ return FAILED;
+ }
+ break;
+ default:
+ DBG1(DBG_ENC, "invalid proposal protocol (%d)", this->protocol_id);
+ return FAILED;
+ }
+ if ((this->protocol_id == 0) || (this->protocol_id >= 4))
+ {
+ /* reserved are not supported */
+ DBG1(DBG_ENC, "invalid protocol");
+ return FAILED;
+ }
+
+ iterator = this->transforms->create_iterator(this->transforms,TRUE);
+ while(iterator->iterate(iterator, (void**)&current_transform))
+ {
+ status = current_transform->verify(current_transform);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "TRANSFORM_SUBSTRUCTURE verification failed");
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* proposal number is checked in SA payload */
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = proposal_substructure_encodings;
+ *rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_proposal_substructure_t *this)
+{
+ return PROPOSAL_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_proposal_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_proposal_substructure_t *this,payload_type_t type)
+{
+}
+
+/**
+ * (re-)compute the length of the payload.
+ */
+static void compute_length(private_proposal_substructure_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_transform;
+ size_t transforms_count = 0;
+ size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
+
+ iterator = this->transforms->create_iterator(this->transforms,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_transform))
+ {
+ length += current_transform->get_length(current_transform);
+ transforms_count++;
+ }
+ iterator->destroy(iterator);
+
+ length += this->spi.len;
+ this->transforms_count = transforms_count;
+ this->proposal_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_proposal_substructure_t *this)
+{
+ compute_length(this);
+ return this->proposal_length;
+}
+
+/**
+ * Implementation of proposal_substructure_t.create_transform_substructure_iterator.
+ */
+static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward)
+{
+ return (this->transforms->create_iterator(this->transforms,forward));
+}
+
+/**
+ * Implementation of proposal_substructure_t.add_transform_substructure.
+ */
+static void add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform)
+{
+ status_t status;
+ if (this->transforms->get_count(this->transforms) > 0)
+ {
+ transform_substructure_t *last_transform;
+ status = this->transforms->get_last(this->transforms,(void **) &last_transform);
+ /* last transform is now not anymore last one */
+ last_transform->set_is_last_transform(last_transform,FALSE);
+
+ }
+ transform->set_is_last_transform(transform,TRUE);
+
+ this->transforms->insert_last(this->transforms,(void *) transform);
+ compute_length(this);
+}
+
+/**
+ * Implementation of proposal_substructure_t.proposal_substructure_t.
+ */
+static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last)
+{
+ this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE;
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_proposal_number.
+ */
+static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
+{
+ this->proposal_number = proposal_number;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_proposal_number.
+ */
+static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
+{
+ return (this->proposal_number);
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_protocol_id.
+ */
+static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
+{
+ this->protocol_id = protocol_id;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_protocol_id.
+ */
+static u_int8_t get_protocol_id(private_proposal_substructure_t *this)
+{
+ return (this->protocol_id);
+}
+
+/**
+ * Implementation of proposal_substructure_t.set_spi.
+ */
+static void set_spi(private_proposal_substructure_t *this, chunk_t spi)
+{
+ /* first delete already set spi value */
+ if (this->spi.ptr != NULL)
+ {
+ free(this->spi.ptr);
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+ compute_length(this);
+ }
+
+ this->spi.ptr = clalloc(spi.ptr,spi.len);
+ this->spi.len = spi.len;
+ this->spi_size = spi.len;
+ compute_length(this);
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_spi.
+ */
+static chunk_t get_spi(private_proposal_substructure_t *this)
+{
+ chunk_t spi;
+ spi.ptr = this->spi.ptr;
+ spi.len = this->spi.len;
+
+ return spi;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_transform_count.
+ */
+static size_t get_transform_count (private_proposal_substructure_t *this)
+{
+ return this->transforms->get_count(this->transforms);
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_spi_size.
+ */
+static size_t get_spi_size (private_proposal_substructure_t *this)
+{
+ return this->spi.len;
+}
+
+/**
+ * Implementation of proposal_substructure_t.get_proposal.
+ */
+proposal_t* get_proposal(private_proposal_substructure_t *this)
+{
+ iterator_t *iterator;
+ transform_substructure_t *transform;
+ proposal_t *proposal;
+ u_int64_t spi;
+
+ proposal = proposal_create(this->protocol_id);
+
+ iterator = this->transforms->create_iterator(this->transforms, TRUE);
+ while (iterator->iterate(iterator, (void**)&transform))
+ {
+ transform_type_t transform_type;
+ u_int16_t transform_id;
+ u_int16_t key_length = 0;
+
+ transform_type = transform->get_transform_type(transform);
+ transform_id = transform->get_transform_id(transform);
+ transform->get_key_length(transform, &key_length);
+
+ proposal->add_algorithm(proposal, transform_type, transform_id, key_length);
+ }
+ iterator->destroy(iterator);
+
+ switch (this->spi.len)
+ {
+ case 4:
+ spi = *((u_int32_t*)this->spi.ptr);
+ break;
+ case 8:
+ spi = *((u_int64_t*)this->spi.ptr);
+ break;
+ default:
+ spi = 0;
+ }
+ proposal->set_spi(proposal, spi);
+
+ return proposal;
+}
+
+/**
+ * Implementation of proposal_substructure_t.clone.
+ */
+static private_proposal_substructure_t* clone_(private_proposal_substructure_t *this)
+{
+ private_proposal_substructure_t *clone;
+ iterator_t *transforms;
+ transform_substructure_t *current_transform;
+
+ clone = (private_proposal_substructure_t *) proposal_substructure_create();
+ clone->next_payload = this->next_payload;
+ clone->proposal_number = this->proposal_number;
+ clone->protocol_id = this->protocol_id;
+ clone->spi_size = this->spi_size;
+ if (this->spi.ptr != NULL)
+ {
+ clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len);
+ clone->spi.len = this->spi.len;
+ }
+
+ transforms = this->transforms->create_iterator(this->transforms,FALSE);
+ while (transforms->iterate(transforms, (void**)&current_transform))
+ {
+ current_transform = current_transform->clone(current_transform);
+ clone->public.add_transform_substructure(&clone->public, current_transform);
+ }
+ transforms->destroy(transforms);
+
+ return clone;
+}
+
+/**
+ * Implements payload_t's and proposal_substructure_t's destroy function.
+ * See #payload_s.destroy or proposal_substructure_s.destroy for description.
+ */
+static void destroy(private_proposal_substructure_t *this)
+{
+ this->transforms->destroy_offset(this->transforms,
+ offsetof(transform_substructure_t, destroy));
+ chunk_free(&this->spi);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create()
+{
+ private_proposal_substructure_t *this = malloc_thing(private_proposal_substructure_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+
+ /* public functions */
+ this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator;
+ this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
+ this->public.set_proposal_number = (void (*) (proposal_substructure_t *,u_int8_t))set_proposal_number;
+ this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number;
+ this->public.set_protocol_id = (void (*) (proposal_substructure_t *,u_int8_t))set_protocol_id;
+ this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id;
+ this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal;
+ this->public.get_proposal = (proposal_t* (*) (proposal_substructure_t*))get_proposal;
+ this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi;
+ this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
+ this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count;
+ this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size;
+ this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone_;
+ this->public.destroy = (void (*) (proposal_substructure_t *)) destroy;
+
+ /* set default values of the fields */
+ this->next_payload = NO_PAYLOAD;
+ this->proposal_length = 0;
+ this->proposal_number = 0;
+ this->protocol_id = 0;
+ this->transforms_count = 0;
+ this->spi_size = 0;
+ this->spi.ptr = NULL;
+ this->spi.len = 0;
+
+ this->transforms = linked_list_create();
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal)
+{
+ transform_substructure_t *transform;
+ private_proposal_substructure_t *this;
+ u_int16_t alg, key_size;
+ enumerator_t *enumerator;
+
+ this = (private_proposal_substructure_t*)proposal_substructure_create();
+
+ /* encryption algorithm is only availble in ESP */
+ enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* integrity algorithms */
+ enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(INTEGRITY_ALGORITHM,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* prf algorithms */
+ enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
+ while (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION,
+ alg, key_size);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* dh groups */
+ enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
+ while (enumerator->enumerate(enumerator, &alg, NULL))
+ {
+ transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP,
+ alg, 0);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* extended sequence numbers */
+ enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
+ while (enumerator->enumerate(enumerator, &alg, NULL))
+ {
+ transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS,
+ alg, 0);
+ add_transform_substructure(this, transform);
+ }
+ enumerator->destroy(enumerator);
+
+ /* add SPI, if necessary */
+ switch (proposal->get_protocol(proposal))
+ {
+ case PROTO_AH:
+ case PROTO_ESP:
+ this->spi_size = this->spi.len = 4;
+ this->spi.ptr = malloc(this->spi_size);
+ *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ break;
+ case PROTO_IKE:
+ if (proposal->get_spi(proposal))
+ { /* IKE only uses SPIS when rekeying, but on initial setup */
+ this->spi_size = this->spi.len = 8;
+ this->spi.ptr = malloc(this->spi_size);
+ *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ }
+ break;
+ default:
+ break;
+ }
+ this->proposal_number = 0;
+ this->protocol_id = proposal->get_protocol(proposal);
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h
new file mode 100644
index 000000000..4934802af
--- /dev/null
+++ b/src/libcharon/encoding/payloads/proposal_substructure.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup proposal_substructure proposal_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef PROPOSAL_SUBSTRUCTURE_H_
+#define PROPOSAL_SUBSTRUCTURE_H_
+
+typedef struct proposal_substructure_t proposal_substructure_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_substructure.h>
+#include <config/proposal.h>
+#include <utils/linked_list.h>
+
+
+/**
+ * Length of the proposal substructure header (without spi).
+ */
+#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
+ *
+ * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
+ */
+struct proposal_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored transform_substructure_t objects.
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_transform_substructure_iterator) (
+ proposal_substructure_t *this, bool forward);
+
+ /**
+ * Adds a transform_substructure_t object to this object.
+ *
+ * @param transform transform_substructure_t object to add
+ */
+ void (*add_transform_substructure) (proposal_substructure_t *this,
+ transform_substructure_t *transform);
+
+ /**
+ * Sets the proposal number of current proposal.
+ *
+ * @param id proposal number to set
+ */
+ void (*set_proposal_number) (proposal_substructure_t *this,
+ u_int8_t proposal_number);
+
+ /**
+ * get proposal number of current proposal.
+ *
+ * @return proposal number of current proposal substructure.
+ */
+ u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
+
+ /**
+ * get the number of transforms in current proposal.
+ *
+ * @return transform count in current proposal
+ */
+ size_t (*get_transform_count) (proposal_substructure_t *this);
+
+ /**
+ * get size of the set spi in bytes.
+ *
+ * @return size of the spi in bytes
+ */
+ size_t (*get_spi_size) (proposal_substructure_t *this);
+
+ /**
+ * Sets the protocol id of current proposal.
+ *
+ * @param id protocol id to set
+ */
+ void (*set_protocol_id) (proposal_substructure_t *this,
+ u_int8_t protocol_id);
+
+ /**
+ * get protocol id of current proposal.
+ *
+ * @return protocol id of current proposal substructure.
+ */
+ u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
+
+ /**
+ * Sets the next_payload field of this substructure
+ *
+ * If this is the last proposal, next payload field is set to 0,
+ * otherwise to 2
+ *
+ * @param is_last When TRUE, next payload field is set to 0, otherwise to 2
+ */
+ void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last);
+
+ /**
+ * Returns the currently set SPI of this proposal.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_spi) (proposal_substructure_t *this);
+
+ /**
+ * Sets the SPI of the current proposal.
+ *
+ * @warning SPI is getting copied
+ *
+ * @param spi chunk_t pointing to the value to set
+ */
+ void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
+
+ /**
+ * Get a proposal_t from the propsal_substructure_t.
+ *
+ * @return proposal_t
+ */
+ proposal_t * (*get_proposal) (proposal_substructure_t *this);
+
+ /**
+ * Clones an proposal_substructure_t object.
+ *
+ * @return cloned object
+ */
+ proposal_substructure_t* (*clone) (proposal_substructure_t *this);
+
+ /**
+ * Destroys an proposal_substructure_t object.
+ */
+ void (*destroy) (proposal_substructure_t *this);
+};
+
+/**
+ * Creates an empty proposal_substructure_t object
+ *
+ * @return proposal_substructure_t object
+ */
+proposal_substructure_t *proposal_substructure_create(void);
+
+/**
+ * Creates a proposal_substructure_t from a proposal_t.
+ *
+ * @param proposal proposal to build a substruct out of it
+ * @return proposal_substructure_t object
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal(
+ proposal_t *proposal);
+
+#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
new file mode 100644
index 000000000..187a8fee0
--- /dev/null
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "sa_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+typedef struct private_sa_payload_t private_sa_payload_t;
+
+/**
+ * Private data of an sa_payload_t object.
+ *
+ */
+struct private_sa_payload_t {
+ /**
+ * Public sa_payload_t interface.
+ */
+ sa_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Proposals in this payload are stored in a linked_list_t.
+ */
+ linked_list_t * proposals;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-SA Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_sa_payload_t.
+ *
+ */
+encoding_rule_t sa_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_sa_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_sa_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole SA payload*/
+ { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
+ /* Proposals are stored in a proposal substructure,
+ offset points to a linked_list_t pointer */
+ { PROPOSALS, offsetof(private_sa_payload_t, proposals) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Proposals> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_sa_payload_t *this)
+{
+ int expected_number = 1, current_number;
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ proposal_substructure_t *current_proposal;
+ bool first = TRUE;
+
+ /* check proposal numbering */
+ iterator = this->proposals->create_iterator(this->proposals,TRUE);
+
+ while(iterator->iterate(iterator, (void**)&current_proposal))
+ {
+ current_number = current_proposal->get_proposal_number(current_proposal);
+ if (current_number < expected_number)
+ {
+ if (current_number != (expected_number + 1))
+ {
+ DBG1(DBG_ENC, "proposal number is %d, expected %d or %d",
+ current_number, expected_number, expected_number + 1);
+ status = FAILED;
+ break;
+ }
+ }
+ else if (current_number < expected_number)
+ {
+ /* must not be smaller then proceeding one */
+ DBG1(DBG_ENC, "proposal number smaller than that of previous proposal");
+ status = FAILED;
+ break;
+ }
+
+ status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "PROPOSAL_SUBSTRUCTURE verification failed");
+ break;
+ }
+ first = FALSE;
+ expected_number = current_number;
+ }
+
+ iterator->destroy(iterator);
+ return status;
+}
+
+
+/**
+ * Implementation of payload_t.destroy and sa_payload_t.destroy.
+ */
+static status_t destroy(private_sa_payload_t *this)
+{
+ this->proposals->destroy_offset(this->proposals,
+ offsetof(proposal_substructure_t, destroy));
+ free(this);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = sa_payload_encodings;
+ *rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_sa_payload_t *this)
+{
+ return SECURITY_ASSOCIATION;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_sa_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_sa_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute length of the payload.
+ */
+static void compute_length (private_sa_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_proposal;
+ size_t length = SA_PAYLOAD_HEADER_LENGTH;
+
+ iterator = this->proposals->create_iterator(this->proposals,TRUE);
+ while (iterator->iterate(iterator, (void **)&current_proposal))
+ {
+ length += current_proposal->get_length(current_proposal);
+ }
+ iterator->destroy(iterator);
+
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_sa_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of sa_payload_t.create_proposal_substructure_iterator.
+ */
+static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward)
+{
+ return this->proposals->create_iterator(this->proposals,forward);
+}
+
+/**
+ * Implementation of sa_payload_t.add_proposal_substructure.
+ */
+static void add_proposal_substructure(private_sa_payload_t *this,proposal_substructure_t *proposal)
+{
+ status_t status;
+ u_int proposal_count = this->proposals->get_count(this->proposals);
+
+ if (proposal_count > 0)
+ {
+ proposal_substructure_t *last_proposal;
+ status = this->proposals->get_last(this->proposals,(void **) &last_proposal);
+ /* last transform is now not anymore last one */
+ last_proposal->set_is_last_proposal(last_proposal, FALSE);
+ }
+ proposal->set_is_last_proposal(proposal, TRUE);
+ proposal->set_proposal_number(proposal, proposal_count + 1);
+ this->proposals->insert_last(this->proposals,(void *) proposal);
+ compute_length(this);
+}
+
+/**
+ * Implementation of sa_payload_t.add_proposal.
+ */
+static void add_proposal(private_sa_payload_t *this, proposal_t *proposal)
+{
+ proposal_substructure_t *substructure;
+
+ substructure = proposal_substructure_create_from_proposal(proposal);
+ add_proposal_substructure(this, substructure);
+}
+
+/**
+ * Implementation of sa_payload_t.get_proposals.
+ */
+static linked_list_t *get_proposals(private_sa_payload_t *this)
+{
+ int struct_number = 0;
+ int ignore_struct_number = 0;
+ iterator_t *iterator;
+ proposal_substructure_t *proposal_struct;
+ linked_list_t *proposal_list;
+
+ /* this list will hold our proposals */
+ proposal_list = linked_list_create();
+
+ /* we do not support proposals split up to two proposal substructures, as
+ * AH+ESP bundles are not supported in RFC4301 anymore.
+ * To handle such structures safely, we just skip proposals with multiple
+ * protocols.
+ */
+ iterator = this->proposals->create_iterator(this->proposals, TRUE);
+ while (iterator->iterate(iterator, (void **)&proposal_struct))
+ {
+ proposal_t *proposal;
+
+ /* check if a proposal has a single protocol */
+ if (proposal_struct->get_proposal_number(proposal_struct) == struct_number)
+ {
+ if (ignore_struct_number < struct_number)
+ {
+ /* remova an already added, if first of series */
+ proposal_list->remove_last(proposal_list, (void**)&proposal);
+ proposal->destroy(proposal);
+ ignore_struct_number = struct_number;
+ }
+ continue;
+ }
+ struct_number++;
+ proposal = proposal_struct->get_proposal(proposal_struct);
+ if (proposal)
+ {
+ proposal_list->insert_last(proposal_list, proposal);
+ }
+ }
+ iterator->destroy(iterator);
+ return proposal_list;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create()
+{
+ private_sa_payload_t *this = malloc_thing(private_sa_payload_t);
+
+ /* public interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator;
+ this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
+ this->public.add_proposal = (void (*) (sa_payload_t*,proposal_t*))add_proposal;
+ this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals;
+ this->public.destroy = (void (*) (sa_payload_t *)) destroy;
+
+ /* set default values of the fields */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
+ this->proposals = linked_list_create();
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
+{
+ iterator_t *iterator;
+ proposal_t *proposal;
+ sa_payload_t *sa_payload = sa_payload_create();
+
+ /* add every payload from the list */
+ iterator = proposals->create_iterator(proposals, TRUE);
+ while (iterator->iterate(iterator, (void**)&proposal))
+ {
+ add_proposal((private_sa_payload_t*)sa_payload, proposal);
+ }
+ iterator->destroy(iterator);
+
+ return sa_payload;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
+{
+ sa_payload_t *sa_payload = sa_payload_create();
+
+ add_proposal((private_sa_payload_t*)sa_payload, proposal);
+
+ return sa_payload;
+}
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
new file mode 100644
index 000000000..25f5a2407
--- /dev/null
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup sa_payload sa_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef SA_PAYLOAD_H_
+#define SA_PAYLOAD_H_
+
+typedef struct sa_payload_t sa_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <utils/linked_list.h>
+
+/**
+ * SA_PAYLOAD length in bytes without any proposal substructure.
+ */
+#define SA_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2-SA Payload.
+ *
+ * The SA Payload format is described in RFC section 3.3.
+ */
+struct sa_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored proposal_substructure_t objects.
+ *
+ * When deleting an proposal using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length()!
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this,
+ bool forward);
+
+ /**
+ * Adds a proposal_substructure_t object to this object.
+ *
+ * @param proposal proposal_substructure_t object to add
+ */
+ void (*add_proposal_substructure) (sa_payload_t *this,
+ proposal_substructure_t *proposal);
+
+ /**
+ * Gets the proposals in this payload as a list.
+ *
+ * @return a list containing proposal_t s
+ */
+ linked_list_t *(*get_proposals) (sa_payload_t *this);
+
+ /**
+ * Add a child proposal (AH/ESP) to the payload.
+ *
+ * @param proposal child proposal to add to the payload
+ */
+ void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
+
+ /**
+ * Destroys an sa_payload_t object.
+ */
+ void (*destroy) (sa_payload_t *this);
+};
+
+/**
+ * Creates an empty sa_payload_t object
+ *
+ * @return created sa_payload_t object
+ */
+sa_payload_t *sa_payload_create(void);
+
+/**
+ * Creates a sa_payload_t object from a list of proposals.
+ *
+ * @param proposals list of proposals to build the payload from
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
+
+/**
+ * Creates a sa_payload_t object from a single proposal.
+ *
+ * This is only for convenience. Use sa_payload_create_from_proposal_list
+ * if you want to add more than one proposal.
+ *
+ * @param proposal proposal from which the payload should be built.
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
+
+#endif /** SA_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
new file mode 100644
index 000000000..f24857591
--- /dev/null
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "traffic_selector_substructure.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
+
+/**
+ * Private data of an traffic_selector_substructure_t object.
+ *
+ */
+struct private_traffic_selector_substructure_t {
+ /**
+ * Public traffic_selector_substructure_t interface.
+ */
+ traffic_selector_substructure_t public;
+
+ /**
+ * Type of traffic selector.
+ */
+ u_int8_t ts_type;
+
+ /**
+ * IP Protocol ID.
+ */
+ u_int8_t ip_protocol_id;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Start port number.
+ */
+ u_int16_t start_port;
+
+ /**
+ * End port number.
+ */
+ u_int16_t end_port;
+
+ /**
+ * Starting address.
+ */
+ chunk_t starting_address;
+
+ /**
+ * Ending address.
+ */
+ chunk_t ending_address;
+};
+
+/**
+ * Encoding rules to parse or generate a TS payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_traffic_selector_substructure_t.
+ *
+ */
+encoding_rule_t traffic_selector_substructure_encodings[] = {
+ /* 1 Byte next ts type*/
+ { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
+ /* 1 Byte IP protocol id*/
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
+ /* 2 Byte start port*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
+ /* 2 Byte end port*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
+ /* starting address is either 4 or 16 byte */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
+ /* ending address is either 4 or 16 byte */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
+
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! TS Type !IP Protocol ID*| Selector Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Start Port* | End Port* |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Starting Address* ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Ending Address* ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_traffic_selector_substructure_t *this)
+{
+ if (this->start_port > this->end_port)
+ {
+ return FAILED;
+ }
+ switch (this->ts_type)
+ {
+ case TS_IPV4_ADDR_RANGE:
+ {
+ if ((this->starting_address.len != 4) ||
+ (this->ending_address.len != 4))
+ {
+ /* ipv4 address must be 4 bytes long */
+ return FAILED;
+ }
+ break;
+ }
+ case TS_IPV6_ADDR_RANGE:
+ {
+ if ((this->starting_address.len != 16) ||
+ (this->ending_address.len != 16))
+ {
+ /* ipv6 address must be 16 bytes long */
+ return FAILED;
+ }
+ break;
+ }
+ default:
+ {
+ /* not supported ts type */
+ return FAILED;
+ }
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of traffic_selector_substructure_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = traffic_selector_substructure_encodings;
+ *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
+{
+ return TRAFFIC_SELECTOR_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
+{
+ return 0;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
+{
+
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_traffic_selector_substructure_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of traffic_selector_substructure_t.get_traffic_selector.
+ */
+static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
+{
+ traffic_selector_t *ts;
+ ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
+ this->starting_address, this->start_port,
+ this->ending_address, this->end_port);
+ return ts;
+}
+
+/**
+ * recompute length field of the payload
+ */
+void compute_length(private_traffic_selector_substructure_t *this)
+{
+ this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
+ this->ending_address.len + this->starting_address.len;
+}
+
+/**
+ * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
+ */
+static void destroy(private_traffic_selector_substructure_t *this)
+{
+ free(this->starting_address.ptr);
+ free(this->ending_address.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create()
+{
+ private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
+ this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
+
+ /* private variables */
+ this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
+ this->start_port = 0;
+ this->end_port = 0;
+ this->starting_address = chunk_empty;
+ this->ending_address = chunk_empty;
+ this->ip_protocol_id = 0;
+ /* must be set to be valid */
+ this->ts_type = TS_IPV4_ADDR_RANGE;
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
+{
+ private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
+ this->ts_type = traffic_selector->get_type(traffic_selector);
+ this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
+ this->start_port = traffic_selector->get_from_port(traffic_selector);
+ this->end_port = traffic_selector->get_to_port(traffic_selector);
+ this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector));
+ this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector));
+
+ compute_length(this);
+
+ return &(this->public);
+}
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.h b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
new file mode 100644
index 000000000..0109fd7f5
--- /dev/null
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup traffic_selector_substructure traffic_selector_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
+#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
+
+typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <selectors/traffic_selector.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
+ */
+#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
+
+/**
+ * Class representing an IKEv2 TRAFFIC SELECTOR.
+ *
+ * The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
+ */
+struct traffic_selector_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of Traffic selector.
+ *
+ * @return type of traffic selector
+ *
+ */
+ ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the type of Traffic selector.
+ *
+ * @param ts_type type of traffic selector
+ */
+ void (*set_ts_type) (traffic_selector_substructure_t *this,
+ ts_type_t ts_type);
+
+ /**
+ * Get the IP protocol ID of Traffic selector.
+ *
+ * @return type of traffic selector
+ *
+ */
+ u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the IP protocol ID of Traffic selector
+ *
+ * @param protocol_id protocol ID of traffic selector
+ */
+ void (*set_protocol_id) (traffic_selector_substructure_t *this,
+ u_int8_t protocol_id);
+
+ /**
+ * Get the start port and address as host_t object.
+ *
+ * Returned host_t object has to get destroyed by the caller.
+ *
+ * @return start host as host_t object
+ *
+ */
+ host_t *(*get_start_host) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the start port and address as host_t object.
+ *
+ * @param start_host start host as host_t object
+ */
+ void (*set_start_host) (traffic_selector_substructure_t *this,
+ host_t *start_host);
+
+ /**
+ * Get the end port and address as host_t object.
+ *
+ * Returned host_t object has to get destroyed by the caller.
+ *
+ * @return end host as host_t object
+ *
+ */
+ host_t *(*get_end_host) (traffic_selector_substructure_t *this);
+
+ /**
+ * Set the end port and address as host_t object.
+ *
+ * @param end_host end host as host_t object
+ */
+ void (*set_end_host) (traffic_selector_substructure_t *this,
+ host_t *end_host);
+
+ /**
+ * Get a traffic_selector_t from this substructure.
+ *
+ * @warning traffic_selector_t must be destroyed after usage.
+ *
+ * @return contained traffic_selector_t
+ */
+ traffic_selector_t *(*get_traffic_selector) (
+ traffic_selector_substructure_t *this);
+
+ /**
+ * Destroys an traffic_selector_substructure_t object.
+ */
+ void (*destroy) (traffic_selector_substructure_t *this);
+};
+
+/**
+ * Creates an empty traffic_selector_substructure_t object.
+ *
+ * TS type is set to default TS_IPV4_ADDR_RANGE!
+ *
+ * @return traffic_selector_substructure_t object
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create(void);
+
+/**
+ * Creates an initialized traffif selector substructure using
+ * the values from a traffic_selector_t.
+ *
+ * @param traffic_selector traffic_selector_t to use for initialization
+ * @return traffic_selector_substructure_t object
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
+ traffic_selector_t *traffic_selector);
+
+#endif /** TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c
new file mode 100644
index 000000000..8bf2ddef4
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_attribute.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <stddef.h>
+
+#include "transform_attribute.h"
+
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+
+typedef struct private_transform_attribute_t private_transform_attribute_t;
+
+/**
+ * Private data of an transform_attribute_t object.
+ *
+ */
+struct private_transform_attribute_t {
+ /**
+ * Public transform_attribute_t interface.
+ */
+ transform_attribute_t public;
+
+ /**
+ * Attribute Format Flag.
+ *
+ * - TRUE means value is stored in attribute_length_or_value
+ * - FALSE means value is stored in attribute_value
+ */
+ bool attribute_format;
+
+ /**
+ * Type of the attribute.
+ */
+ u_int16_t attribute_type;
+
+ /**
+ * Attribute Length if attribute_format is 0, attribute Value otherwise.
+ */
+ u_int16_t attribute_length_or_value;
+
+ /**
+ * Attribute value as chunk if attribute_format is 0 (FALSE).
+ */
+ chunk_t attribute_value;
+};
+
+
+ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
+ "ATTRIBUTE_UNDEFINED");
+ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
+ "KEY_LENGTH");
+ENUM_END(transform_attribute_type_name, KEY_LENGTH);
+
+/**
+ * Encoding rules to parse or generate a Transform attribute.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_transform_attribute_t.
+ *
+ */
+encoding_rule_t transform_attribute_encodings[] = {
+ /* Flag defining the format of this payload */
+ { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
+ /* Length or value, depending on the attribute format flag */
+ { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) },
+ /* Value of attribute if attribute format flag is zero */
+ { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !A! Attribute Type ! AF=0 Attribute Length !
+ !F! ! AF=1 Attribute Value !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! AF=0 Attribute Value !
+ ! AF=1 Not Transmitted !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_transform_attribute_t *this)
+{
+ if (this->attribute_type != KEY_LENGTH)
+ {
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = transform_attribute_encodings;
+ *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_transform_attribute_t *this)
+{
+ return TRANSFORM_ATTRIBUTE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_transform_attribute_t *this)
+{
+ return (NO_PAYLOAD);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_transform_attribute_t *this,payload_type_t type)
+{
+}
+
+/**
+ * Implementation of transform_attribute_t.get_length.
+ */
+static size_t get_length(private_transform_attribute_t *this)
+{
+ if (this->attribute_format == TRUE)
+ {
+ /*Attribute size is only 4 byte */
+ return 4;
+ }
+ return (this->attribute_length_or_value + 4);
+}
+
+/**
+ * Implementation of transform_attribute_t.set_value_chunk.
+ */
+static void set_value_chunk(private_transform_attribute_t *this, chunk_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+
+ if (value.len > 2)
+ {
+ this->attribute_value.ptr = clalloc(value.ptr,value.len);
+ this->attribute_value.len = value.len;
+ this->attribute_length_or_value = value.len;
+ /* attribute has not a fixed length */
+ this->attribute_format = FALSE;
+ }
+ else
+ {
+ memcpy(&(this->attribute_length_or_value),value.ptr,value.len);
+ }
+}
+
+/**
+ * Implementation of transform_attribute_t.set_value.
+ */
+static void set_value(private_transform_attribute_t *this, u_int16_t value)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ /* free existing value */
+ free(this->attribute_value.ptr);
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ }
+ this->attribute_length_or_value = value;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_value_chunk.
+ */
+static chunk_t get_value_chunk (private_transform_attribute_t *this)
+{
+ chunk_t value;
+
+ if (this->attribute_format == FALSE)
+ {
+ value.ptr = this->attribute_value.ptr;
+ value.len = this->attribute_value.len;
+ }
+ else
+ {
+ value.ptr = (void *) &(this->attribute_length_or_value);
+ value.len = 2;
+ }
+
+ return value;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_value.
+ */
+static u_int16_t get_value (private_transform_attribute_t *this)
+{
+ return this->attribute_length_or_value;
+}
+
+
+/**
+ * Implementation of transform_attribute_t.set_attribute_type.
+ */
+static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
+{
+ this->attribute_type = type & 0x7FFF;
+}
+
+/**
+ * Implementation of transform_attribute_t.get_attribute_type.
+ */
+static u_int16_t get_attribute_type (private_transform_attribute_t *this)
+{
+ return this->attribute_type;
+}
+
+/**
+ * Implementation of transform_attribute_t.clone.
+ */
+static transform_attribute_t * _clone(private_transform_attribute_t *this)
+{
+ private_transform_attribute_t *new_clone;
+
+ new_clone = (private_transform_attribute_t *) transform_attribute_create();
+
+ new_clone->attribute_format = this->attribute_format;
+ new_clone->attribute_type = this->attribute_type;
+ new_clone->attribute_length_or_value = this->attribute_length_or_value;
+
+ if (!new_clone->attribute_format)
+ {
+ new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len);
+ new_clone->attribute_value.len = this->attribute_value.len;
+ }
+
+ return (transform_attribute_t *) new_clone;
+}
+
+/**
+ * Implementation of transform_attribute_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_transform_attribute_t *this)
+{
+ if (this->attribute_value.ptr != NULL)
+ {
+ free(this->attribute_value.ptr);
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+transform_attribute_t *transform_attribute_create()
+{
+ private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t);
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
+ this->public.set_value = (void (*) (transform_attribute_t *,u_int16_t)) set_value;
+ this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
+ this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value;
+ this->public.set_attribute_type = (void (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type;
+ this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type;
+ this->public.clone = (transform_attribute_t * (*) (transform_attribute_t *)) _clone;
+ this->public.destroy = (void (*) (transform_attribute_t *)) destroy;
+
+ /* set default values of the fields */
+ this->attribute_format = TRUE;
+ this->attribute_type = 0;
+ this->attribute_length_or_value = 0;
+ this->attribute_value.ptr = NULL;
+ this->attribute_value.len = 0;
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header.
+ */
+transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
+{
+ transform_attribute_t *attribute = transform_attribute_create();
+ attribute->set_attribute_type(attribute,KEY_LENGTH);
+ attribute->set_value(attribute,key_length);
+ return attribute;
+}
diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h
new file mode 100644
index 000000000..a5fe0154b
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_attribute.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup transform_attribute transform_attribute
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRANSFORM_ATTRIBUTE_H_
+#define TRANSFORM_ATTRIBUTE_H_
+
+typedef enum transform_attribute_type_t transform_attribute_type_t;
+typedef struct transform_attribute_t transform_attribute_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+
+/**
+ * Type of the attribute, as in IKEv2 RFC 3.3.5.
+ */
+enum transform_attribute_type_t {
+ ATTRIBUTE_UNDEFINED = 16384,
+ KEY_LENGTH = 14
+};
+
+/**
+ * enum name for transform_attribute_type_t.
+ */
+extern enum_name_t *transform_attribute_type_names;
+
+/**
+ * Class representing an IKEv2- TRANSFORM Attribute.
+ *
+ * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
+ */
+struct transform_attribute_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Returns the currently set value of the attribute.
+ *
+ * Returned data are not copied.
+ *
+ * @return chunk_t pointing to the value
+ */
+ chunk_t (*get_value_chunk) (transform_attribute_t *this);
+
+ /**
+ * Returns the currently set value of the attribute.
+ *
+ * Returned data are not copied.
+ *
+ * @return value
+ */
+ u_int16_t (*get_value) (transform_attribute_t *this);
+
+ /**
+ * Sets the value of the attribute.
+ *
+ * Value is getting copied.
+ *
+ * @param value chunk_t pointing to the value to set
+ */
+ void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
+
+ /**
+ * Sets the value of the attribute.
+ *
+ * @param value value to set
+ */
+ void (*set_value) (transform_attribute_t *this, u_int16_t value);
+
+ /**
+ * Sets the type of the attribute.
+ *
+ * @param type type to set (most significant bit is set to zero)
+ */
+ void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
+
+ /**
+ * get the type of the attribute.
+ *
+ * @return type of the value
+ */
+ u_int16_t (*get_attribute_type) (transform_attribute_t *this);
+
+ /**
+ * Clones an transform_attribute_t object.
+ *
+ * @return cloned transform_attribute_t object
+ */
+ transform_attribute_t * (*clone) (transform_attribute_t *this);
+
+ /**
+ * Destroys an transform_attribute_t object.
+ */
+ void (*destroy) (transform_attribute_t *this);
+};
+
+/**
+ * Creates an empty transform_attribute_t object.
+ *
+ * @return transform_attribute_t object
+ */
+transform_attribute_t *transform_attribute_create(void);
+
+/**
+ * Creates an transform_attribute_t of type KEY_LENGTH.
+ *
+ * @param key_length key length in bytes
+ * @return transform_attribute_t object
+ */
+transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
+
+#endif /** TRANSFORM_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c
new file mode 100644
index 000000000..c94f6c1a2
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_substructure.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "transform_substructure.h"
+
+#include <encoding/payloads/transform_attribute.h>
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+#include <utils/linked_list.h>
+#include <daemon.h>
+
+
+typedef struct private_transform_substructure_t private_transform_substructure_t;
+
+/**
+ * Private data of an transform_substructure_t object.
+ *
+ */
+struct private_transform_substructure_t {
+ /**
+ * Public transform_substructure_t interface.
+ */
+ transform_substructure_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t transform_length;
+
+
+ /**
+ * Type of the transform.
+ */
+ u_int8_t transform_type;
+
+ /**
+ * Transform ID.
+ */
+ u_int16_t transform_id;
+
+ /**
+ * Transforms Attributes are stored in a linked_list_t.
+ */
+ linked_list_t *attributes;
+};
+
+
+/**
+ * Encoding rules to parse or generate a Transform substructure.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_transform_substructure_t.
+ *
+ */
+encoding_rule_t transform_substructure_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* Length of the whole transform substructure*/
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
+ /* transform type is a number of 8 bit */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, 0 },
+ /* tranform ID is a number of 8 bit */
+ { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
+ /* Attributes are stored in a transform attribute,
+ offset points to a linked_list_t pointer */
+ { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! 0 (last) or 3 ! RESERVED ! Transform Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !Transform Type ! RESERVED ! Transform ID !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Transform Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_transform_substructure_t *this)
+{
+ status_t status = SUCCESS;
+ iterator_t *iterator;
+ payload_t *current_attributes;
+
+ if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3))
+ {
+ /* must be 0 or 3 */
+ DBG1(DBG_ENC, "inconsistent next payload");
+ return FAILED;
+ }
+
+ switch (this->transform_type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ case PSEUDO_RANDOM_FUNCTION:
+ case INTEGRITY_ALGORITHM:
+ case DIFFIE_HELLMAN_GROUP:
+ case EXTENDED_SEQUENCE_NUMBERS:
+ /* we don't check transform ID, we want to reply
+ * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
+ break;
+ default:
+ {
+ DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
+ return FAILED;
+ }
+ }
+ iterator = this->attributes->create_iterator(this->attributes,TRUE);
+
+ while(iterator->iterate(iterator, (void**)&current_attributes))
+ {
+ status = current_attributes->verify(current_attributes);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "TRANSFORM_ATTRIBUTE verification failed");
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* proposal number is checked in SA payload */
+ return status;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = transform_substructure_encodings;
+ *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_type(private_transform_substructure_t *this)
+{
+ return TRANSFORM_SUBSTRUCTURE;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_transform_substructure_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length (private_transform_substructure_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_attribute;
+ size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+
+ iterator = this->attributes->create_iterator(this->attributes,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_attribute))
+ {
+ length += current_attribute->get_length(current_attribute);
+ }
+ iterator->destroy(iterator);
+
+ this->transform_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_transform_substructure_t *this)
+{
+ compute_length(this);
+ return this->transform_length;
+}
+
+/**
+ * Implementation of transform_substructure_t.create_transform_attribute_iterator.
+ */
+static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward)
+{
+ return this->attributes->create_iterator(this->attributes,forward);
+}
+
+/**
+ * Implementation of transform_substructure_t.add_transform_attribute.
+ */
+static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
+{
+ this->attributes->insert_last(this->attributes,(void *) attribute);
+ compute_length(this);
+}
+
+/**
+ * Implementation of transform_substructure_t.set_is_last_transform.
+ */
+static void set_is_last_transform (private_transform_substructure_t *this, bool is_last)
+{
+ this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_is_last_transform.
+ */
+static bool get_is_last_transform (private_transform_substructure_t *this)
+{
+ return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_transform_substructure_t *this,payload_type_t type)
+{
+}
+
+/**
+ * Implementation of transform_substructure_t.set_transform_type.
+ */
+static void set_transform_type (private_transform_substructure_t *this,u_int8_t type)
+{
+ this->transform_type = type;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_transform_type.
+ */
+static u_int8_t get_transform_type (private_transform_substructure_t *this)
+{
+ return this->transform_type;
+}
+
+/**
+ * Implementation of transform_substructure_t.set_transform_id.
+ */
+static void set_transform_id (private_transform_substructure_t *this,u_int16_t id)
+{
+ this->transform_id = id;
+}
+
+/**
+ * Implementation of transform_substructure_t.get_transform_id.
+ */
+static u_int16_t get_transform_id (private_transform_substructure_t *this)
+{
+ return this->transform_id;
+}
+
+/**
+ * Implementation of transform_substructure_t.clone.
+ */
+static transform_substructure_t *clone_(private_transform_substructure_t *this)
+{
+ private_transform_substructure_t *clone;
+ iterator_t *attributes;
+ transform_attribute_t *current_attribute;
+
+ clone = (private_transform_substructure_t *) transform_substructure_create();
+ clone->next_payload = this->next_payload;
+ clone->transform_type = this->transform_type;
+ clone->transform_id = this->transform_id;
+
+ attributes = this->attributes->create_iterator(this->attributes, FALSE);
+ while (attributes->iterate(attributes, (void**)&current_attribute))
+ {
+ current_attribute = current_attribute->clone(current_attribute);
+ clone->public.add_transform_attribute(&clone->public, current_attribute);
+ }
+ attributes->destroy(attributes);
+
+ return &clone->public;
+}
+
+
+/**
+ * Implementation of transform_substructure_t.get_key_length.
+ */
+static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
+{
+ iterator_t *attributes;
+ transform_attribute_t *current_attribute;
+
+ attributes = this->attributes->create_iterator(this->attributes, TRUE);
+ while (attributes->iterate(attributes, (void**)&current_attribute))
+ {
+ if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
+ {
+ *key_length = current_attribute->get_value(current_attribute);
+ attributes->destroy(attributes);
+ return SUCCESS;
+ }
+ }
+ attributes->destroy(attributes);
+ return FAILED;
+}
+
+
+/**
+ * Implementation of transform_substructure_t.destroy and payload_t.destroy.
+ */
+static void destroy(private_transform_substructure_t *this)
+{
+ this->attributes->destroy_offset(this->attributes,
+ offsetof(transform_attribute_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+transform_substructure_t *transform_substructure_create()
+{
+ private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t);
+
+ /* payload interface */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator;
+ this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
+ this->public.set_is_last_transform = (void (*) (transform_substructure_t *,bool)) set_is_last_transform;
+ this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
+ this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
+ this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
+ this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
+ this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
+ this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
+ this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone_;
+ this->public.destroy = (void (*) (transform_substructure_t *)) destroy;
+
+ /* set default values of the fields */
+ this->next_payload = NO_PAYLOAD;
+ this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ this->transform_id = 0;
+ this->transform_type = 0;
+ this->attributes = linked_list_create();
+
+ return (&(this->public));
+}
+
+/*
+ * Described in header
+ */
+transform_substructure_t *transform_substructure_create_type(
+ transform_type_t transform_type,
+ u_int16_t transform_id, u_int16_t key_length)
+{
+ transform_substructure_t *transform = transform_substructure_create();
+
+ transform->set_transform_type(transform,transform_type);
+ transform->set_transform_id(transform,transform_id);
+
+ if (key_length)
+ {
+ transform_attribute_t *attribute;
+
+ attribute = transform_attribute_create_key_length(key_length);
+ transform->add_transform_attribute(transform, attribute);
+
+ }
+ return transform;
+}
+
diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h
new file mode 100644
index 000000000..5d31f8c0a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/transform_substructure.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup transform_substructure transform_substructure
+ * @{ @ingroup payloads
+ */
+
+#ifndef TRANSFORM_SUBSTRUCTURE_H_
+#define TRANSFORM_SUBSTRUCTURE_H_
+
+typedef struct transform_substructure_t transform_substructure_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/transform_attribute.h>
+#include <utils/linked_list.h>
+#include <crypto/diffie_hellman.h>
+#include <crypto/signers/signer.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <config/proposal.h>
+
+
+/**
+ * IKEv1 Value for a transform payload.
+ */
+#define TRANSFORM_TYPE_VALUE 3
+
+/**
+ * Length of the transform substructure header in bytes.
+ */
+#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
+
+
+/**
+ * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
+ *
+ * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
+ */
+struct transform_substructure_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an iterator of stored transform_attribute_t objects.
+ *
+ * When deleting an transform attribute using this iterator,
+ * the length of this transform substructure has to be refreshed
+ * by calling get_length().
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object.
+ */
+ iterator_t * (*create_transform_attribute_iterator) (
+ transform_substructure_t *this, bool forward);
+
+ /**
+ * Adds a transform_attribute_t object to this object.
+ *
+ * @param proposal transform_attribute_t object to add
+ */
+ void (*add_transform_attribute) (transform_substructure_t *this,
+ transform_attribute_t *attribute);
+
+ /**
+ * Sets the next_payload field of this substructure
+ *
+ * If this is the last transform, next payload field is set to 0,
+ * otherwise to 3
+ *
+ * @param is_last When TRUE, next payload field is set to 0, otherwise to 3
+ */
+ void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
+
+ /**
+ * Checks if this is the last transform.
+ *
+ * @return TRUE if this is the last Transform, FALSE otherwise
+ */
+ bool (*get_is_last_transform) (transform_substructure_t *this);
+
+ /**
+ * Sets transform type of the current transform substructure.
+ *
+ * @param type type value to set
+ */
+ void (*set_transform_type) (transform_substructure_t *this, u_int8_t type);
+
+ /**
+ * get transform type of the current transform.
+ *
+ * @return Transform type of current transform substructure.
+ */
+ u_int8_t (*get_transform_type) (transform_substructure_t *this);
+
+ /**
+ * Sets transform id of the current transform substructure.
+ *
+ * @param id transform id to set
+ */
+ void (*set_transform_id) (transform_substructure_t *this, u_int16_t id);
+
+ /**
+ * get transform id of the current transform.
+ *
+ * @return Transform id of current transform substructure.
+ */
+ u_int16_t (*get_transform_id) (transform_substructure_t *this);
+
+ /**
+ * get transform id of the current transform.
+ *
+ * @param key_length The key length is written to this location
+ * @return
+ * - SUCCESS if a key length attribute is contained
+ * - FAILED if no key length attribute is part of this
+ * transform or key length uses more then 16 bit!
+ */
+ status_t (*get_key_length) (transform_substructure_t *this,
+ u_int16_t *key_length);
+
+ /**
+ * Clones an transform_substructure_t object.
+ *
+ * @return cloned transform_substructure_t object
+ */
+ transform_substructure_t* (*clone) (transform_substructure_t *this);
+
+ /**
+ * Destroys an transform_substructure_t object.
+ */
+ void (*destroy) (transform_substructure_t *this);
+};
+
+/**
+ * Creates an empty transform_substructure_t object.
+ *
+ * @return created transform_substructure_t object
+ */
+transform_substructure_t *transform_substructure_create(void);
+
+/**
+ * Creates an empty transform_substructure_t object.
+ *
+ * The key length is used for the transport types ENCRYPTION_ALGORITHM,
+ * PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all
+ * other transport types the key_length parameter is not used
+ *
+ * @param transform_type type of transform to create
+ * @param transform_id transform id specifying the specific algorithm of a transform type
+ * @param key_length Key length for key lenght attribute
+ * @return transform_substructure_t object
+ */
+transform_substructure_t *transform_substructure_create_type(
+ transform_type_t transform_type, u_int16_t transform_id,
+ u_int16_t key_length);
+
+#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c
new file mode 100644
index 000000000..6bf3e4293
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ts_payload.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "ts_payload.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+typedef struct private_ts_payload_t private_ts_payload_t;
+
+/**
+ * Private data of an ts_payload_t object.
+ *
+ */
+struct private_ts_payload_t {
+ /**
+ * Public ts_payload_t interface.
+ */
+ ts_payload_t public;
+
+ /**
+ * TRUE if this TS payload is of type TSi, FALSE for TSr.
+ */
+ bool is_initiator;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Number of traffic selectors
+ */
+ u_int8_t number_of_traffic_selectors;
+
+ /**
+ * Contains the traffic selectors of type traffic_selector_substructure_t.
+ */
+ linked_list_t *traffic_selectors;
+};
+
+/**
+ * Encoding rules to parse or generate a TS payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_ts_payload_t.
+ *
+ */
+encoding_rule_t ts_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ts_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_ts_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)},
+ /* 1 Byte TS type*/
+ { U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, 0 },
+ /* some ts data bytes, length is defined in PAYLOAD_LENGTH */
+ { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Number of TSs ! RESERVED !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Traffic Selectors> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_ts_payload_t *this)
+{
+ iterator_t *iterator;
+ payload_t *current_traffic_selector;
+ status_t status = SUCCESS;
+
+ if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
+ {
+ /* must be the same */
+ return FAILED;
+ }
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
+ while(iterator->iterate(iterator, (void**)&current_traffic_selector))
+ {
+ status = current_traffic_selector->verify(current_traffic_selector);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return status;
+}
+
+/**
+ * Implementation of ts_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ts_payload_encodings;
+ *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_ts_payload_t *this)
+{
+ if (this->is_initiator)
+ {
+ return TRAFFIC_SELECTOR_INITIATOR;
+ }
+ else
+ {
+ return TRAFFIC_SELECTOR_RESPONDER;
+ }
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_ts_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_ts_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length (private_ts_payload_t *this)
+{
+ iterator_t *iterator;
+ size_t ts_count = 0;
+ size_t length = TS_PAYLOAD_HEADER_LENGTH;
+ payload_t *current_traffic_selector;
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
+ while (iterator->iterate(iterator, (void**)&current_traffic_selector))
+ {
+ length += current_traffic_selector->get_length(current_traffic_selector);
+ ts_count++;
+ }
+ iterator->destroy(iterator);
+
+ this->number_of_traffic_selectors= ts_count;
+ this->payload_length = length;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_ts_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+/**
+ * Implementation of ts_payload_t.get_initiator.
+ */
+static bool get_initiator (private_ts_payload_t *this)
+{
+ return (this->is_initiator);
+}
+
+/**
+ * Implementation of ts_payload_t.set_initiator.
+ */
+static void set_initiator (private_ts_payload_t *this,bool is_initiator)
+{
+ this->is_initiator = is_initiator;
+}
+
+/**
+ * Implementation of ts_payload_t.add_traffic_selector_substructure.
+ */
+static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
+{
+ this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
+ this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
+}
+
+/**
+ * Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
+ */
+static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
+{
+ return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
+}
+
+/**
+ * Implementation of ts_payload_t.get_traffic_selectors.
+ */
+static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
+{
+ traffic_selector_t *ts;
+ iterator_t *iterator;
+ traffic_selector_substructure_t *ts_substructure;
+ linked_list_t *ts_list = linked_list_create();
+
+ iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts_substructure))
+ {
+ ts = ts_substructure->get_traffic_selector(ts_substructure);
+ ts_list->insert_last(ts_list, (void*)ts);
+ }
+ iterator->destroy(iterator);
+
+ return ts_list;
+}
+
+/**
+ * Implementation of payload_t.destroy and ts_payload_t.destroy.
+ */
+static void destroy(private_ts_payload_t *this)
+{
+ this->traffic_selectors->destroy_offset(this->traffic_selectors,
+ offsetof(payload_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+ts_payload_t *ts_payload_create(bool is_initiator)
+{
+ private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (ts_payload_t *)) destroy;
+ this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
+ this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
+ this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
+ this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
+ this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
+ this->is_initiator = is_initiator;
+ this->number_of_traffic_selectors = 0;
+ this->traffic_selectors = linked_list_create();
+
+ return &(this->public);
+}
+
+/*
+ * Described in header
+ */
+ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
+{
+ iterator_t *iterator;
+ traffic_selector_t *ts;
+ traffic_selector_substructure_t *ts_substructure;
+ private_ts_payload_t *this;
+
+ this = (private_ts_payload_t*)ts_payload_create(is_initiator);
+
+ iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts))
+ {
+ ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
+ this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
+ }
+ iterator->destroy(iterator);
+
+ return &(this->public);
+}
+
diff --git a/src/libcharon/encoding/payloads/ts_payload.h b/src/libcharon/encoding/payloads/ts_payload.h
new file mode 100644
index 000000000..d322ff1a8
--- /dev/null
+++ b/src/libcharon/encoding/payloads/ts_payload.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ts_payload ts_payload
+ * @{ @ingroup payloads
+ */
+
+
+#ifndef TS_PAYLOAD_H_
+#define TS_PAYLOAD_H_
+
+typedef struct ts_payload_t ts_payload_t;
+
+#include <library.h>
+#include <utils/linked_list.h>
+#include <selectors/traffic_selector.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/traffic_selector_substructure.h>
+
+/**
+ * Length of a TS payload without the Traffic selectors.
+ */
+#define TS_PAYLOAD_HEADER_LENGTH 8
+
+
+/**
+ * Class representing an IKEv2 TS payload.
+ *
+ * The TS payload format is described in RFC section 3.13.
+ */
+struct ts_payload_t {
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of TSpayload (TSi or TSr).
+ *
+ * @return
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ */
+ bool (*get_initiator) (ts_payload_t *this);
+
+ /**
+ * Set the type of TS payload (TSi or TSr).
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ */
+ void (*set_initiator) (ts_payload_t *this,bool is_initiator);
+
+ /**
+ * Adds a traffic_selector_substructure_t object to this object.
+ *
+ * @param traffic_selector traffic_selector_substructure_t object to add
+ */
+ void (*add_traffic_selector_substructure) (ts_payload_t *this,
+ traffic_selector_substructure_t *traffic_selector);
+
+ /**
+ * Creates an iterator of stored traffic_selector_substructure_t objects.
+ *
+ * When removing an traffic_selector_substructure_t object
+ * using this iterator, the length of this payload
+ * has to get refreshed by calling payload_t.get_length!
+ *
+ * @param forward iterator direction (TRUE: front to end)
+ * @return created iterator_t object
+ */
+ iterator_t *(*create_traffic_selector_substructure_iterator) (
+ ts_payload_t *this, bool forward);
+
+ /**
+ * Get a list of nested traffic selectors as traffic_selector_t.
+ *
+ * Resulting list and its traffic selectors must be destroyed after usage
+ *
+ * @return list of traffic selectors
+ */
+ linked_list_t *(*get_traffic_selectors) (ts_payload_t *this);
+
+ /**
+ * Destroys an ts_payload_t object.
+ */
+ void (*destroy) (ts_payload_t *this);
+};
+
+/**
+ * Creates an empty ts_payload_t object.
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ * @return ts_payload_t object
+ */
+ts_payload_t *ts_payload_create(bool is_initiator);
+
+/**
+ * Creates ts_payload with a list of traffic_selector_t
+ *
+ * @param is_initiator
+ * - TRUE if this payload is of type TSi
+ * - FALSE if this payload is of type TSr
+ * @param traffic_selectors list of traffic selectors to include
+ * @return ts_payload_t object
+ */
+ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator,
+ linked_list_t *traffic_selectors);
+
+#endif /** TS_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
new file mode 100644
index 000000000..dd5547dc3
--- /dev/null
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "unknown_payload.h"
+
+
+
+typedef struct private_unknown_payload_t private_unknown_payload_t;
+
+/**
+ * Private data of an unknown_payload_t object.
+ */
+struct private_unknown_payload_t {
+
+ /**
+ * Public unknown_payload_t interface.
+ */
+ unknown_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * The contained data.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse an payload which is not further specified.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_unknown_payload_t.
+ *
+ */
+encoding_rule_t unknown_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_unknown_payload_t, next_payload)},
+ /* the critical bit */
+ { FLAG, offsetof(private_unknown_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)},
+ /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
+ { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Data of any type ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_unknown_payload_t *this)
+{
+ /* can't do any checks, so we assume its good */
+ return SUCCESS;
+}
+
+/**
+ * Implementation of payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = unknown_payload_encodings;
+ *rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_unknown_payload_t *this)
+{
+ return UNKNOWN_PAYLOAD;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_unknown_payload_t *this)
+{
+ return (this->next_payload);
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_unknown_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_unknown_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of unknown_payload_t.get_data.
+ */
+static bool is_critical(private_unknown_payload_t *this)
+{
+ return this->critical;
+}
+
+/**
+ * Implementation of unknown_payload_t.get_data.
+ */
+static chunk_t get_data (private_unknown_payload_t *this)
+{
+ return (this->data);
+}
+
+/**
+ * Implementation of payload_t.destroy and unknown_payload_t.destroy.
+ */
+static void destroy(private_unknown_payload_t *this)
+{
+ if (this->data.ptr != NULL)
+ {
+ chunk_free(&(this->data));
+ }
+
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+unknown_payload_t *unknown_payload_create()
+{
+ private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t);
+
+ /* interface functions */
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+
+ /* public functions */
+ this->public.destroy = (void (*) (unknown_payload_t *)) destroy;
+ this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical;
+ this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data;
+
+ /* private variables */
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+
+ return (&(this->public));
+}
diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h
new file mode 100644
index 000000000..c761ed2b6
--- /dev/null
+++ b/src/libcharon/encoding/payloads/unknown_payload.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unknown_payload unknown_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef UNKNOWN_PAYLOAD_H_
+#define UNKNOWN_PAYLOAD_H_
+
+typedef struct unknown_payload_t unknown_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Header length of the unknown payload.
+ */
+#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Payload which can't be processed further.
+ *
+ * When the parser finds an unknown payload, he builds an instance of
+ * this class. This allows further processing of this payload, such as
+ * a check for the critical bit in the header.
+ */
+struct unknown_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the raw data of this payload, without
+ * the generic payload header.
+ *
+ * Returned data are NOT copied and must not be freed.
+ *
+ * @return data as chunk_t
+ */
+ chunk_t (*get_data) (unknown_payload_t *this);
+
+ /**
+ * Get the critical flag.
+ *
+ * @return TRUE if payload is critical, FALSE if not
+ */
+ bool (*is_critical) (unknown_payload_t *this);
+
+ /**
+ * Destroys an unknown_payload_t object.
+ */
+ void (*destroy) (unknown_payload_t *this);
+};
+
+/**
+ * Creates an empty unknown_payload_t object.
+ *
+ * @return unknown_payload_t object
+ */
+unknown_payload_t *unknown_payload_create(void);
+
+#endif /** UNKNOWN_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c
new file mode 100644
index 000000000..bf33d2418
--- /dev/null
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+
+#include "vendor_id_payload.h"
+
+typedef struct private_vendor_id_payload_t private_vendor_id_payload_t;
+
+/**
+ * Private data of an vendor_id_payload_t object.
+ */
+struct private_vendor_id_payload_t {
+
+ /**
+ * Public vendor_id_payload_t interface.
+ */
+ vendor_id_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Critical flag.
+ */
+ bool critical;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * The contained data.
+ */
+ chunk_t data;
+};
+
+/**
+ * Encoding rules to parse or generate a VENDOR ID payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_vendor_id_payload_t.
+ */
+encoding_rule_t vendor_id_payload_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_vendor_id_payload_t, critical) },
+ /* 7 Bit reserved bits, nowhere stored */
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ { RESERVED_BIT, 0 },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)},
+ /* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
+ { VID_DATA, offsetof(private_vendor_id_payload_t, data) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ + !
+ ~ VID Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Implementation of payload_t.verify.
+ */
+static status_t verify(private_vendor_id_payload_t *this)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of vendor_id_payload_t.get_encoding_rules.
+ */
+static void get_encoding_rules(private_vendor_id_payload_t *this,
+ encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = vendor_id_payload_encodings;
+ *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t);
+}
+
+/**
+ * Implementation of payload_t.get_type.
+ */
+static payload_type_t get_payload_type(private_vendor_id_payload_t *this)
+{
+ return VENDOR_ID;
+}
+
+/**
+ * Implementation of payload_t.get_next_type.
+ */
+static payload_type_t get_next_type(private_vendor_id_payload_t *this)
+{
+ return this->next_payload;
+}
+
+/**
+ * Implementation of payload_t.set_next_type.
+ */
+static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * Implementation of payload_t.get_length.
+ */
+static size_t get_length(private_vendor_id_payload_t *this)
+{
+ return this->payload_length;
+}
+
+/**
+ * Implementation of vendor_id_payload_t.get_data.
+ */
+static chunk_t get_data(private_vendor_id_payload_t *this)
+{
+ return this->data;
+}
+
+/**
+ * Implementation of payload_t.destroy and vendor_id_payload_t.destroy.
+ */
+static void destroy(private_vendor_id_payload_t *this)
+{
+ free(this->data.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+vendor_id_payload_t *vendor_id_payload_create()
+{
+ private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t);
+
+ this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
+ this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
+ this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
+ this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
+ this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
+ this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
+ this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
+ this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data;
+
+ this->critical = FALSE;
+ this->next_payload = NO_PAYLOAD;
+ this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
+ this->data = chunk_empty;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
+{
+ private_vendor_id_payload_t *this;
+
+ this = (private_vendor_id_payload_t*)vendor_id_payload_create();
+ this->payload_length += data.len;
+ this->data = data;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h
new file mode 100644
index 000000000..241535cac
--- /dev/null
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vendor_id_payload vendor_id_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef VENDOR_ID_PAYLOAD_H_
+#define VENDOR_ID_PAYLOAD_H_
+
+typedef struct vendor_id_payload_t vendor_id_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Length of a VENDOR ID payload without the VID data in bytes.
+ */
+#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv2 VENDOR ID payload.
+ *
+ * The VENDOR ID payload format is described in RFC section 3.12.
+ */
+struct vendor_id_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the VID data.
+ *
+ * @return VID data, pointing to an internal chunk_t
+ */
+ chunk_t (*get_data)(vendor_id_payload_t *this);
+};
+
+/**
+ * Creates an empty Vendor ID payload.
+ *
+ * @return vendor ID payload
+ */
+vendor_id_payload_t *vendor_id_payload_create();
+
+/**
+ * Creates a vendor ID payload using a chunk of data
+ *
+ * @param data data to use in vendor ID payload, gets owned by payload
+ * @return vendor ID payload
+ */
+vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data);
+
+#endif /** VENDOR_ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
new file mode 100644
index 000000000..64a43a7fc
--- /dev/null
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "kernel_interface.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_interface_t private_kernel_interface_t;
+
+/**
+ * Private data of a kernel_interface_t object.
+ */
+struct private_kernel_interface_t {
+
+ /**
+ * Public part of kernel_interface_t object.
+ */
+ kernel_interface_t public;
+
+ /**
+ * ipsec interface
+ */
+ kernel_ipsec_t *ipsec;
+
+ /**
+ * network interface
+ */
+ kernel_net_t *net;
+};
+
+METHOD(kernel_interface_t, get_spi, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->get_spi(this->ipsec, src, dst, protocol, reqid, spi);
+}
+
+METHOD(kernel_interface_t, get_cpi, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->get_cpi(this->ipsec, src, dst, reqid, cpi);
+}
+
+METHOD(kernel_interface_t, add_sa, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
+ 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 encap, bool inbound, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
+ lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi,
+ encap, inbound, src_ts, dst_ts);
+}
+
+METHOD(kernel_interface_t, update_sa, status_t,
+ private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
+ new_src, new_dst, encap, new_encap);
+}
+
+METHOD(kernel_interface_t, query_sa, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
+}
+
+METHOD(kernel_interface_t, del_sa, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int16_t cpi)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi);
+}
+
+METHOD(kernel_interface_t, add_policy, status_t,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
+ direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
+}
+
+METHOD(kernel_interface_t, query_policy, status_t,
+ private_kernel_interface_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
+ direction, use_time);
+}
+
+METHOD(kernel_interface_t, del_policy, status_t,
+ private_kernel_interface_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
+ direction, unrouted);
+}
+
+METHOD(kernel_interface_t, get_source_addr, host_t*,
+ private_kernel_interface_t *this, host_t *dest, host_t *src)
+{
+ if (!this->net)
+ {
+ return NULL;
+ }
+ return this->net->get_source_addr(this->net, dest, src);
+}
+
+METHOD(kernel_interface_t, get_nexthop, host_t*,
+ private_kernel_interface_t *this, host_t *dest)
+{
+ if (!this->net)
+ {
+ return NULL;
+ }
+ return this->net->get_nexthop(this->net, dest);
+}
+
+METHOD(kernel_interface_t, get_interface, char*,
+ private_kernel_interface_t *this, host_t *host)
+{
+ if (!this->net)
+ {
+ return NULL;
+ }
+ return this->net->get_interface(this->net, host);
+}
+
+METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
+ private_kernel_interface_t *this, bool include_down_ifaces,
+ bool include_virtual_ips)
+{
+ if (!this->net)
+ {
+ return enumerator_create_empty();
+ }
+ return this->net->create_address_enumerator(this->net, include_down_ifaces,
+ include_virtual_ips);
+}
+
+METHOD(kernel_interface_t, add_ip, status_t,
+ private_kernel_interface_t *this, host_t *virtual_ip, host_t *iface_ip)
+{
+ if (!this->net)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->add_ip(this->net, virtual_ip, iface_ip);
+}
+
+METHOD(kernel_interface_t, del_ip, status_t,
+ private_kernel_interface_t *this, host_t *virtual_ip)
+{
+ if (!this->net)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->del_ip(this->net, virtual_ip);
+}
+
+METHOD(kernel_interface_t, add_route, status_t,
+ private_kernel_interface_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ if (!this->net)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->add_route(this->net, dst_net, prefixlen, gateway,
+ src_ip, if_name);
+}
+
+METHOD(kernel_interface_t, del_route, status_t,
+ private_kernel_interface_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ if (!this->net)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->del_route(this->net, dst_net, prefixlen, gateway,
+ src_ip, if_name);
+}
+
+METHOD(kernel_interface_t, bypass_socket, bool,
+ private_kernel_interface_t *this, int fd, int family)
+{
+ if (!this->ipsec)
+ {
+ return FALSE;
+ }
+ return this->ipsec->bypass_socket(this->ipsec, fd, family);
+}
+
+METHOD(kernel_interface_t, get_address_by_ts, status_t,
+ private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
+{
+ enumerator_t *addrs;
+ host_t *host;
+ int family;
+ bool found = FALSE;
+
+ DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
+
+ /* if we have a family which includes localhost, we do not
+ * search for an IP, we use the default */
+ family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
+
+ if (family == AF_INET)
+ {
+ host = host_create_from_string("127.0.0.1", 0);
+ }
+ else
+ {
+ host = host_create_from_string("::1", 0);
+ }
+
+ if (ts->includes(ts, host))
+ {
+ *ip = host_create_any(family);
+ host->destroy(host);
+ DBG2(DBG_KNL, "using host %H", *ip);
+ return SUCCESS;
+ }
+ host->destroy(host);
+
+ addrs = create_address_enumerator(this, TRUE, TRUE);
+ while (addrs->enumerate(addrs, (void**)&host))
+ {
+ if (ts->includes(ts, host))
+ {
+ found = TRUE;
+ *ip = host->clone(host);
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+
+ if (!found)
+ {
+ DBG1(DBG_KNL, "no local address found in traffic selector %R", ts);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "using host %H", *ip);
+ return SUCCESS;
+}
+
+
+METHOD(kernel_interface_t, add_ipsec_interface, void,
+ private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
+{
+ if (!this->ipsec)
+ {
+ this->ipsec = constructor();
+ }
+}
+
+METHOD(kernel_interface_t, remove_ipsec_interface, void,
+ private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
+{
+ /* TODO: replace if interface currently in use */
+}
+
+METHOD(kernel_interface_t, add_net_interface, void,
+ private_kernel_interface_t *this, kernel_net_constructor_t constructor)
+{
+ if (!this->net)
+ {
+ this->net = constructor();
+ }
+}
+
+METHOD(kernel_interface_t, remove_net_interface, void,
+ private_kernel_interface_t *this, kernel_net_constructor_t constructor)
+{
+ /* TODO: replace if interface currently in use */
+}
+
+METHOD(kernel_interface_t, destroy, void,
+ private_kernel_interface_t *this)
+{
+ DESTROY_IF(this->ipsec);
+ DESTROY_IF(this->net);
+ free(this);
+}
+
+/*
+ * Described in header-file
+ */
+kernel_interface_t *kernel_interface_create()
+{
+ private_kernel_interface_t *this;
+
+ INIT(this,
+ .public = {
+ .get_spi = _get_spi,
+ .get_cpi = _get_cpi,
+ .add_sa = _add_sa,
+ .update_sa = _update_sa,
+ .query_sa = _query_sa,
+ .del_sa = _del_sa,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .get_source_addr = _get_source_addr,
+ .get_nexthop = _get_nexthop,
+ .get_interface = _get_interface,
+ .create_address_enumerator = _create_address_enumerator,
+ .add_ip = _add_ip,
+ .del_ip = _del_ip,
+ .add_route = _add_route,
+ .del_route = _del_route,
+ .bypass_socket = _bypass_socket,
+
+ .get_address_by_ts = _get_address_by_ts,
+ .add_ipsec_interface = _add_ipsec_interface,
+ .remove_ipsec_interface = _remove_ipsec_interface,
+ .add_net_interface = _add_net_interface,
+ .remove_net_interface = _remove_net_interface,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
new file mode 100644
index 000000000..4a62e76b8
--- /dev/null
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_interface kernel_interface
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_INTERFACE_H_
+#define KERNEL_INTERFACE_H_
+
+typedef struct kernel_interface_t kernel_interface_t;
+
+#include <utils/host.h>
+#include <crypto/prf_plus.h>
+#include <encoding/payloads/proposal_substructure.h>
+
+#include <kernel/kernel_ipsec.h>
+#include <kernel/kernel_net.h>
+
+/**
+ * Constructor function for ipsec kernel interface
+ */
+typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void);
+
+/**
+ * Constructor function for network kernel interface
+ */
+typedef kernel_net_t* (*kernel_net_constructor_t)(void);
+
+/**
+ * Manager and wrapper for different kernel interfaces.
+ *
+ * The kernel interface handles the communication with the kernel
+ * for SA and policy management and interface and IP address management.
+ */
+struct kernel_interface_t {
+
+ /**
+ * Get a SPI from the kernel.
+ *
+ * @param src source address of SA
+ * @param dst destination address of SA
+ * @param protocol protocol for SA (ESP/AH)
+ * @param reqid unique ID for this SA
+ * @param spi allocated spi
+ * @return SUCCESS if operation completed
+ */
+ status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi);
+
+ /**
+ * Get a Compression Parameter Index (CPI) from the kernel.
+ *
+ * @param src source address of SA
+ * @param dst destination address of SA
+ * @param reqid unique ID for the corresponding SA
+ * @param cpi allocated cpi
+ * @return SUCCESS if operation completed
+ */
+ status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi);
+
+ /**
+ * Add an SA to the SAD.
+ *
+ * add_sa() may update an already allocated
+ * SPI (via get_spi). In this case, the replace
+ * flag must be set.
+ * This function does install a single SA for a
+ * single protocol in one direction.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param reqid unique ID for this SA
+ * @param lifetime lifetime_cfg_t for this SA
+ * @param enc_alg Algorithm to use for encryption (ESP only)
+ * @param enc_key key to use for encryption
+ * @param int_alg Algorithm to use for integrity protection
+ * @param int_key key to use for integrity protection
+ * @param mode mode of the SA (tunnel, transport)
+ * @param ipcomp IPComp transform to use
+ * @param cpi CPI for IPComp
+ * @param encap enable UDP encapsulation for NAT traversal
+ * @param inbound TRUE if this is an inbound SA
+ * @param src_ts traffic selector with BEET source address
+ * @param dst_ts traffic selector with BEET destination address
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_sa) (kernel_interface_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ 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 encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
+
+ /**
+ * Update the hosts on an installed SA.
+ *
+ * We cannot directly update the destination address as the kernel
+ * requires the spi, the protocol AND the destination address (and family)
+ * to identify SAs. Therefore if the destination address changed we
+ * create a new SA and delete the old one.
+ *
+ * @param spi SPI of the SA
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp, 0 if no IPComp is used
+ * @param src current source address
+ * @param dst current destination address
+ * @param new_src new source address
+ * @param new_dst new destination address
+ * @param encap current use of UDP encapsulation
+ * @param new_encap new use of UDP encapsulation
+ * @return SUCCESS if operation completed, NOT_SUPPORTED if
+ * the kernel interface can't update the SA
+ */
+ status_t (*update_sa)(kernel_interface_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap);
+
+ /**
+ * Query the number of bytes processed by an SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param[out] bytes the number of bytes processed by SA
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+
+ /**
+ * Delete a previously installed SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp or 0
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+
+ /**
+ * Add a policy to the SPD.
+ *
+ * A policy is always associated to an SA. Traffic which matches a
+ * policy is handled by the SA with the same reqid.
+ *
+ * @param src source address of SA
+ * @param dst dest address of SA
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param spi SPI of SA
+ * @param protocol protocol to use to protect traffic (AH/ESP)
+ * @param reqid unique ID of an SA to use to enforce policy
+ * @param mode mode of SA (tunnel, transport)
+ * @param ipcomp the IPComp transform used
+ * @param cpi CPI for IPComp
+ * @param routed TRUE, if this policy is routed in the kernel
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_policy) (kernel_interface_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed);
+
+ /**
+ * Query the use time of a policy.
+ *
+ * The use time of a policy is the time the policy was used
+ * for the last time.
+ *
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param[out] use_time the time of this SA's last use
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_policy) (kernel_interface_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time);
+
+ /**
+ * Remove a policy from the SPD.
+ *
+ * The kernel interface implements reference counting for policies.
+ * If the same policy is installed multiple times (in the case of rekeying),
+ * the reference counter is increased. del_policy() decreases the ref counter
+ * and removes the policy only when no more references are available.
+ *
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param unrouted TRUE, if this policy is unrouted from the kernel
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_policy) (kernel_interface_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction,
+ bool unrouted);
+
+ /**
+ * Get our outgoing source address for a destination.
+ *
+ * Does a route lookup to get the source address used to reach dest.
+ * The returned host is allocated and must be destroyed.
+ * An optional src address can be used to check if a route is available
+ * for given source to dest.
+ *
+ * @param dest target destination address
+ * @param src source address to check, or NULL
+ * @return outgoing source address, NULL if unreachable
+ */
+ host_t* (*get_source_addr)(kernel_interface_t *this,
+ host_t *dest, host_t *src);
+
+ /**
+ * Get the next hop for a destination.
+ *
+ * Does a route lookup to get the next hop used to reach dest.
+ * The returned host is allocated and must be destroyed.
+ *
+ * @param dest target destination address
+ * @return next hop address, NULL if unreachable
+ */
+ host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest);
+
+ /**
+ * Get the interface name of a local address.
+ *
+ * @param host address to get interface name from
+ * @return allocated interface name, or NULL if not found
+ */
+ char* (*get_interface) (kernel_interface_t *this, host_t *host);
+
+ /**
+ * Creates an enumerator over all local addresses.
+ *
+ * This function blocks an internal cached address list until the
+ * enumerator gets destroyed.
+ * The hosts are read-only, do not modify of free.
+ *
+ * @param include_down_ifaces TRUE to enumerate addresses from down interfaces
+ * @param include_virtual_ips TRUE to enumerate virtual ip addresses
+ * @return enumerator over host_t's
+ */
+ enumerator_t *(*create_address_enumerator) (kernel_interface_t *this,
+ bool include_down_ifaces, bool include_virtual_ips);
+
+ /**
+ * Add a virtual IP to an interface.
+ *
+ * Virtual IPs are attached to an interface. If an IP is added multiple
+ * times, the IP is refcounted and not removed until del_ip() was called
+ * as many times as add_ip().
+ * The virtual IP is attached to the interface where the iface_ip is found.
+ *
+ * @param virtual_ip virtual ip address to assign
+ * @param iface_ip IP of an interface to attach virtual IP
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_ip) (kernel_interface_t *this, host_t *virtual_ip,
+ host_t *iface_ip);
+
+ /**
+ * Remove a virtual IP from an interface.
+ *
+ * The kernel interface uses refcounting, see add_ip().
+ *
+ * @param virtual_ip virtual ip address to assign
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip);
+
+ /**
+ * Add a route.
+ *
+ * @param dst_net destination net
+ * @param prefixlen destination net prefix length
+ * @param gateway gateway for this route
+ * @param src_ip sourc ip of the route
+ * @param if_name name of the interface the route is bound to
+ * @return SUCCESS if operation completed
+ * ALREADY_DONE if the route already exists
+ */
+ status_t (*add_route) (kernel_interface_t *this, chunk_t dst_net, u_int8_t prefixlen,
+ host_t *gateway, host_t *src_ip, char *if_name);
+
+ /**
+ * Delete a route.
+ *
+ * @param dst_net destination net
+ * @param prefixlen destination net prefix length
+ * @param gateway gateway for this route
+ * @param src_ip sourc ip of the route
+ * @param if_name name of the interface the route is bound to
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_route) (kernel_interface_t *this, chunk_t dst_net, u_int8_t prefixlen,
+ host_t *gateway, host_t *src_ip, char *if_name);
+
+ /**
+ * Set up a bypass policy for a given socket.
+ *
+ * @param fd socket file descriptor to setup policy for
+ * @param family protocol family of the socket
+ * @return TRUE of policy set up successfully
+ */
+ bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
+
+ /**
+ * manager methods
+ */
+
+ /**
+ * Tries to find an ip address of a local interface that is included in the
+ * supplied traffic selector.
+ *
+ * @param ts traffic selector
+ * @param ip returned ip (has to be destroyed)
+ * @return SUCCESS if address found
+ */
+ status_t (*get_address_by_ts) (kernel_interface_t *this,
+ traffic_selector_t *ts, host_t **ip);
+
+ /**
+ * Register an ipsec kernel interface constructor on the manager.
+ *
+ * @param create constructor to register
+ */
+ void (*add_ipsec_interface)(kernel_interface_t *this, kernel_ipsec_constructor_t create);
+
+ /**
+ * Unregister an ipsec kernel interface constructor.
+ *
+ * @param create constructor to unregister
+ */
+ void (*remove_ipsec_interface)(kernel_interface_t *this, kernel_ipsec_constructor_t create);
+
+ /**
+ * Register a network kernel interface constructor on the manager.
+ *
+ * @param create constructor to register
+ */
+ void (*add_net_interface)(kernel_interface_t *this, kernel_net_constructor_t create);
+
+ /**
+ * Unregister a network kernel interface constructor.
+ *
+ * @param create constructor to unregister
+ */
+ void (*remove_net_interface)(kernel_interface_t *this, kernel_net_constructor_t create);
+
+ /**
+ * Destroys a kernel_interface_manager_t object.
+ */
+ void (*destroy) (kernel_interface_t *this);
+};
+
+/**
+ * Creates an object of type kernel_interface_t.
+ */
+kernel_interface_t *kernel_interface_create(void);
+
+#endif /** KERNEL_INTERFACE_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_ipsec.c b/src/libcharon/kernel/kernel_ipsec.c
new file mode 100644
index 000000000..5b0335b16
--- /dev/null
+++ b/src/libcharon/kernel/kernel_ipsec.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "kernel_ipsec.h"
+
+ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_BEET,
+ "TRANSPORT",
+ "TUNNEL",
+ "BEET",
+);
+
+ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
+ "in",
+ "out",
+ "fwd"
+);
+
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
new file mode 100644
index 000000000..300464cf6
--- /dev/null
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_ipsec kernel_ipsec
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_IPSEC_H_
+#define KERNEL_IPSEC_H_
+
+typedef enum ipsec_mode_t ipsec_mode_t;
+typedef enum policy_dir_t policy_dir_t;
+typedef struct kernel_ipsec_t kernel_ipsec_t;
+
+#include <utils/host.h>
+#include <crypto/prf_plus.h>
+#include <config/proposal.h>
+#include <config/child_cfg.h>
+
+/**
+ * Mode of a CHILD_SA.
+ */
+enum ipsec_mode_t {
+ /** transport mode, no inner address */
+ MODE_TRANSPORT = 1,
+ /** tunnel mode, inner and outer addresses */
+ MODE_TUNNEL,
+ /** BEET mode, tunnel mode but fixed, bound inner addresses */
+ MODE_BEET,
+};
+
+/**
+ * enum names for ipsec_mode_t.
+ */
+extern enum_name_t *ipsec_mode_names;
+
+/**
+ * Direction of a policy. These are equal to those
+ * defined in xfrm.h, but we want to stay implementation
+ * neutral here.
+ */
+enum policy_dir_t {
+ /** Policy for inbound traffic */
+ POLICY_IN = 0,
+ /** Policy for outbound traffic */
+ POLICY_OUT = 1,
+ /** Policy for forwarded traffic */
+ POLICY_FWD = 2,
+};
+
+/**
+ * enum names for policy_dir_t.
+ */
+extern enum_name_t *policy_dir_names;
+
+/**
+ * Interface to the ipsec subsystem of the kernel.
+ *
+ * The kernel ipsec interface handles the communication with the kernel
+ * for SA and policy management. It allows setup of these, and provides
+ * further the handling of kernel events.
+ * Policy information are cached in the interface. This is necessary to do
+ * reference counting. The Linux kernel does not allow the same policy
+ * installed twice, but we need this as CHILD_SA exist multiple times
+ * when rekeying. Thats why we do reference counting of policies.
+ */
+struct kernel_ipsec_t {
+
+ /**
+ * Get a SPI from the kernel.
+ *
+ * @param src source address of SA
+ * @param dst destination address of SA
+ * @param protocol protocol for SA (ESP/AH)
+ * @param reqid unique ID for this SA
+ * @param spi allocated spi
+ * @return SUCCESS if operation completed
+ */
+ status_t (*get_spi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi);
+
+ /**
+ * Get a Compression Parameter Index (CPI) from the kernel.
+ *
+ * @param src source address of SA
+ * @param dst destination address of SA
+ * @param reqid unique ID for the corresponding SA
+ * @param cpi allocated cpi
+ * @return SUCCESS if operation completed
+ */
+ status_t (*get_cpi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi);
+
+ /**
+ * Add an SA to the SAD.
+ *
+ * add_sa() may update an already allocated
+ * SPI (via get_spi). In this case, the replace
+ * flag must be set.
+ * This function does install a single SA for a
+ * single protocol in one direction.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param reqid unique ID for this SA
+ * @param lifetime lifetime_cfg_t for this SA
+ * @param enc_alg Algorithm to use for encryption (ESP only)
+ * @param enc_key key to use for encryption
+ * @param int_alg Algorithm to use for integrity protection
+ * @param int_key key to use for integrity protection
+ * @param mode mode of the SA (tunnel, transport)
+ * @param ipcomp IPComp transform to use
+ * @param cpi CPI for IPComp
+ * @param encap enable UDP encapsulation for NAT traversal
+ * @param inbound TRUE if this is an inbound SA
+ * @param src_ts traffic selector with BEET source address
+ * @param dst_ts traffic selector with BEET destination address
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_sa) (kernel_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ 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 encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
+
+ /**
+ * Update the hosts on an installed SA.
+ *
+ * We cannot directly update the destination address as the kernel
+ * requires the spi, the protocol AND the destination address (and family)
+ * to identify SAs. Therefore if the destination address changed we
+ * create a new SA and delete the old one.
+ *
+ * @param spi SPI of the SA
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp, 0 if no IPComp is used
+ * @param src current source address
+ * @param dst current destination address
+ * @param new_src new source address
+ * @param new_dst new destination address
+ * @param encap current use of UDP encapsulation
+ * @param new_encap new use of UDP encapsulation
+ * @return SUCCESS if operation completed, NOT_SUPPORTED if
+ * the kernel interface can't update the SA
+ */
+ status_t (*update_sa)(kernel_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap);
+
+ /**
+ * Query the number of bytes processed by an SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param[out] bytes the number of bytes processed by SA
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+
+ /**
+ * Delete a previusly installed SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp or 0
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+
+ /**
+ * Add a policy to the SPD.
+ *
+ * A policy is always associated to an SA. Traffic which matches a
+ * policy is handled by the SA with the same reqid.
+ *
+ * @param src source address of SA
+ * @param dst dest address of SA
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param spi SPI of SA
+ * @param protocol protocol to use to protect traffic (AH/ESP)
+ * @param reqid unique ID of an SA to use to enforce policy
+ * @param mode mode of SA (tunnel, transport)
+ * @param ipcomp the IPComp transform used
+ * @param cpi CPI for IPComp
+ * @param routed TRUE, if this policy is routed in the kernel
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_policy) (kernel_ipsec_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed);
+
+ /**
+ * Query the use time of a policy.
+ *
+ * The use time of a policy is the time the policy was used for the last
+ * time. It is not the system time, but a monotonic timestamp as returned
+ * by time_monotonic.
+ *
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param[out] use_time the monotonic timestamp of this SA's last use
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_policy) (kernel_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time);
+
+ /**
+ * Remove a policy from the SPD.
+ *
+ * The kernel interface implements reference counting for policies.
+ * If the same policy is installed multiple times (in the case of rekeying),
+ * the reference counter is increased. del_policy() decreases the ref counter
+ * and removes the policy only when no more references are available.
+ *
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param unrouted TRUE, if this policy is unrouted from the kernel
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_policy) (kernel_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction,
+ bool unrouted);
+
+ /**
+ * Install a bypass policy for the given socket.
+ *
+ * @param fd socket file descriptor to setup policy for
+ * @param family protocol family of the socket
+ * @return TRUE of policy set up successfully
+ */
+ bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
+
+ /**
+ * Destroy the implementation.
+ */
+ void (*destroy) (kernel_ipsec_t *this);
+};
+
+#endif /** KERNEL_IPSEC_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_net.h b/src/libcharon/kernel/kernel_net.h
new file mode 100644
index 000000000..efb221f88
--- /dev/null
+++ b/src/libcharon/kernel/kernel_net.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_net kernel_net
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_NET_H_
+#define KERNEL_NET_H_
+
+typedef struct kernel_net_t kernel_net_t;
+
+#include <utils/enumerator.h>
+#include <utils/host.h>
+
+/**
+ * Interface to the network subsystem of the kernel.
+ *
+ * The kernel network interface handles the communication with the kernel
+ * for interface and IP address management.
+ */
+struct kernel_net_t {
+
+ /**
+ * Get our outgoing source address for a destination.
+ *
+ * Does a route lookup to get the source address used to reach dest.
+ * The returned host is allocated and must be destroyed.
+ * An optional src address can be used to check if a route is available
+ * for given source to dest.
+ *
+ * @param dest target destination address
+ * @param src source address to check, or NULL
+ * @return outgoing source address, NULL if unreachable
+ */
+ host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest, host_t *src);
+
+ /**
+ * Get the next hop for a destination.
+ *
+ * Does a route lookup to get the next hop used to reach dest.
+ * The returned host is allocated and must be destroyed.
+ *
+ * @param dest target destination address
+ * @return next hop address, NULL if unreachable
+ */
+ host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest);
+
+ /**
+ * Get the interface name of a local address.
+ *
+ * @param host address to get interface name from
+ * @return allocated interface name, or NULL if not found
+ */
+ char* (*get_interface) (kernel_net_t *this, host_t *host);
+
+ /**
+ * Creates an enumerator over all local addresses.
+ *
+ * This function blocks an internal cached address list until the
+ * enumerator gets destroyed.
+ * The hosts are read-only, do not modify of free.
+ *
+ * @param include_down_ifaces TRUE to enumerate addresses from down interfaces
+ * @param include_virtual_ips TRUE to enumerate virtual ip addresses
+ * @return enumerator over host_t's
+ */
+ enumerator_t *(*create_address_enumerator) (kernel_net_t *this,
+ bool include_down_ifaces, bool include_virtual_ips);
+
+ /**
+ * Add a virtual IP to an interface.
+ *
+ * Virtual IPs are attached to an interface. If an IP is added multiple
+ * times, the IP is refcounted and not removed until del_ip() was called
+ * as many times as add_ip().
+ * The virtual IP is attached to the interface where the iface_ip is found.
+ *
+ * @param virtual_ip virtual ip address to assign
+ * @param iface_ip IP of an interface to attach virtual IP
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_ip) (kernel_net_t *this, host_t *virtual_ip,
+ host_t *iface_ip);
+
+ /**
+ * Remove a virtual IP from an interface.
+ *
+ * The kernel interface uses refcounting, see add_ip().
+ *
+ * @param virtual_ip virtual ip address to assign
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_ip) (kernel_net_t *this, host_t *virtual_ip);
+
+ /**
+ * Add a route.
+ *
+ * @param dst_net destination net
+ * @param prefixlen destination net prefix length
+ * @param gateway gateway for this route
+ * @param src_ip sourc ip of the route
+ * @param if_name name of the interface the route is bound to
+ * @return SUCCESS if operation completed
+ * ALREADY_DONE if the route already exists
+ */
+ status_t (*add_route) (kernel_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+ host_t *gateway, host_t *src_ip, char *if_name);
+
+ /**
+ * Delete a route.
+ *
+ * @param dst_net destination net
+ * @param prefixlen destination net prefix length
+ * @param gateway gateway for this route
+ * @param src_ip sourc ip of the route
+ * @param if_name name of the interface the route is bound to
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_route) (kernel_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+ host_t *gateway, host_t *src_ip, char *if_name);
+
+ /**
+ * Destroy the implementation.
+ */
+ void (*destroy) (kernel_net_t *this);
+};
+
+#endif /** KERNEL_NET_H_ @}*/
diff --git a/src/libcharon/network/packet.c b/src/libcharon/network/packet.c
new file mode 100644
index 000000000..19db362f7
--- /dev/null
+++ b/src/libcharon/network/packet.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "packet.h"
+
+typedef struct private_packet_t private_packet_t;
+
+/**
+ * Private data of an packet_t object.
+ */
+struct private_packet_t {
+
+ /**
+ * Public part of a packet_t object.
+ */
+ packet_t public;
+
+ /**
+ * source address
+ */
+ host_t *source;
+
+ /**
+ * destination address
+ */
+ host_t *destination;
+
+ /**
+ * message data
+ */
+ chunk_t data;
+};
+
+METHOD(packet_t, set_source, void,
+ private_packet_t *this, host_t *source)
+{
+ DESTROY_IF(this->source);
+ this->source = source;
+}
+
+METHOD(packet_t, set_destination, void,
+ private_packet_t *this, host_t *destination)
+{
+ DESTROY_IF(this->destination);
+ this->destination = destination;
+}
+
+METHOD(packet_t, get_source, host_t*,
+ private_packet_t *this)
+{
+ return this->source;
+}
+
+METHOD(packet_t, get_destination, host_t*,
+ private_packet_t *this)
+{
+ return this->destination;
+}
+
+METHOD(packet_t, get_data, chunk_t,
+ private_packet_t *this)
+{
+ return this->data;
+}
+
+METHOD(packet_t, set_data, void,
+ private_packet_t *this, chunk_t data)
+{
+ free(this->data.ptr);
+ this->data = data;
+}
+
+METHOD(packet_t, destroy, void,
+ private_packet_t *this)
+{
+ DESTROY_IF(this->source);
+ DESTROY_IF(this->destination);
+ free(this->data.ptr);
+ free(this);
+}
+
+METHOD(packet_t, clone_, packet_t*,
+ private_packet_t *this)
+{
+ packet_t *other;
+
+ other = packet_create();
+ if (this->destination != NULL)
+ {
+ other->set_destination(other, this->destination->clone(this->destination));
+ }
+ if (this->source != NULL)
+ {
+ other->set_source(other, this->source->clone(this->source));
+ }
+ if (this->data.ptr != NULL)
+ {
+ other->set_data(other, chunk_clone(this->data));
+ }
+ return other;
+}
+
+/*
+ * Documented in header
+ */
+packet_t *packet_create(void)
+{
+ private_packet_t *this;
+
+ INIT(this,
+ .public = {
+ .set_data = _set_data,
+ .get_data = _get_data,
+ .set_source = _set_source,
+ .get_source = _get_source,
+ .set_destination = _set_destination,
+ .get_destination = _get_destination,
+ .clone = _clone_,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/network/packet.h b/src/libcharon/network/packet.h
new file mode 100644
index 000000000..18d82c6fc
--- /dev/null
+++ b/src/libcharon/network/packet.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup packet packet
+ * @{ @ingroup network
+ */
+
+#ifndef PACKET_H_
+#define PACKET_H_
+
+typedef struct packet_t packet_t;
+
+#include <library.h>
+#include <utils/host.h>
+
+/**
+ * Abstraction of an UDP-Packet, contains data, sender and receiver.
+ */
+struct packet_t {
+
+ /**
+ * Set the source address.
+ *
+ * Set host_t is now owned by packet_t, it will destroy
+ * it if necessary.
+ *
+ * @param source address to set as source
+ */
+ void (*set_source) (packet_t *packet, host_t *source);
+
+ /**
+ * Set the destination address.
+ *
+ * Set host_t is now owned by packet_t, it will destroy
+ * it if necessary.
+ *
+ * @param source address to set as destination
+ */
+ void (*set_destination) (packet_t *packet, host_t *destination);
+
+ /**
+ * Get the source address.
+ *
+ * Set host_t is still owned by packet_t, clone it
+ * if needed.
+ *
+ * @return source address
+ */
+ host_t *(*get_source) (packet_t *packet);
+
+ /**
+ * Get the destination address.
+ *
+ * Set host_t is still owned by packet_t, clone it
+ * if needed.
+ *
+ * @return destination address
+ */
+ host_t *(*get_destination) (packet_t *packet);
+
+ /**
+ * Get the data from the packet.
+ *
+ * The data pointed by the chunk is still owned
+ * by the packet. Clone it if needed.
+ *
+ * @return chunk containing the data
+ */
+ chunk_t (*get_data) (packet_t *packet);
+
+ /**
+ * Set the data in the packet.
+ *
+ * Supplied chunk data is now owned by the
+ * packet. It will free it.
+ *
+ * @param data chunk with data to set
+ */
+ void (*set_data) (packet_t *packet, chunk_t data);
+
+ /**
+ * Clones a packet_t object.
+ *
+ * @param clone clone of the packet
+ */
+ packet_t* (*clone) (packet_t *packet);
+
+ /**
+ * Destroy the packet, freeing contained data.
+ */
+ void (*destroy) (packet_t *packet);
+};
+
+/**
+ * create an empty packet
+ *
+ * @return packet_t object
+ */
+packet_t *packet_create(void);
+
+#endif /** PACKET_H_ @}*/
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
new file mode 100644
index 000000000..df897021a
--- /dev/null
+++ b/src/libcharon/network/receiver.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "receiver.h"
+
+#include <daemon.h>
+#include <network/socket.h>
+#include <network/packet.h>
+#include <processing/jobs/job.h>
+#include <processing/jobs/process_message_job.h>
+#include <processing/jobs/callback_job.h>
+#include <crypto/hashers/hasher.h>
+
+/** lifetime of a cookie, in seconds */
+#define COOKIE_LIFETIME 10
+/** how many times to reuse the secret */
+#define COOKIE_REUSE 10000
+/** default value for private_receiver_t.cookie_threshold */
+#define COOKIE_THRESHOLD_DEFAULT 10
+/** default value for private_receiver_t.block_threshold */
+#define BLOCK_THRESHOLD_DEFAULT 5
+/** length of the secret to use for cookie calculation */
+#define SECRET_LENGTH 16
+
+typedef struct private_receiver_t private_receiver_t;
+
+/**
+ * Private data of a receiver_t object.
+ */
+struct private_receiver_t {
+ /**
+ * Public part of a receiver_t object.
+ */
+ receiver_t public;
+
+ /**
+ * Threads job receiving packets
+ */
+ callback_job_t *job;
+
+ /**
+ * current secret to use for cookie calculation
+ */
+ char secret[SECRET_LENGTH];
+
+ /**
+ * previous secret used to verify older cookies
+ */
+ char secret_old[SECRET_LENGTH];
+
+ /**
+ * how many times we have used "secret" so far
+ */
+ u_int32_t secret_used;
+
+ /**
+ * time we did the cookie switch
+ */
+ u_int32_t secret_switch;
+
+ /**
+ * time offset to use, hides our system time
+ */
+ u_int32_t secret_offset;
+
+ /**
+ * the RNG to use for secret generation
+ */
+ rng_t *rng;
+
+ /**
+ * hasher to use for cookie calculation
+ */
+ hasher_t *hasher;
+
+ /**
+ * require cookies after this many half open IKE_SAs
+ */
+ u_int32_t cookie_threshold;
+
+ /**
+ * how many half open IKE_SAs per peer before blocking
+ */
+ u_int32_t block_threshold;
+
+ /**
+ * Delay for receiving incoming packets, to simulate larger RTT
+ */
+ u_int receive_delay;
+};
+
+/**
+ * send a notify back to the sender
+ */
+static void send_notify(message_t *request, notify_type_t type, chunk_t data)
+{
+ if (request->get_request(request) &&
+ request->get_exchange_type(request) == IKE_SA_INIT)
+ {
+ message_t *response;
+ host_t *src, *dst;
+ packet_t *packet;
+ ike_sa_id_t *ike_sa_id;
+
+ response = message_create();
+ dst = request->get_source(request);
+ src = request->get_destination(request);
+ response->set_source(response, src->clone(src));
+ response->set_destination(response, dst->clone(dst));
+ response->set_exchange_type(response, request->get_exchange_type(request));
+ response->set_request(response, FALSE);
+ response->set_message_id(response, 0);
+ ike_sa_id = request->get_ike_sa_id(request);
+ ike_sa_id->switch_initiator(ike_sa_id);
+ response->set_ike_sa_id(response, ike_sa_id);
+ response->add_notify(response, FALSE, type, data);
+ if (response->generate(response, NULL, NULL, &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ response->destroy(response);
+ }
+ }
+}
+
+/**
+ * build a cookie
+ */
+static chunk_t cookie_build(private_receiver_t *this, message_t *message,
+ u_int32_t t, chunk_t secret)
+{
+ u_int64_t spi = message->get_initiator_spi(message);
+ host_t *ip = message->get_source(message);
+ chunk_t input, hash;
+
+ /* COOKIE = t | sha1( IPi | SPIi | t | secret ) */
+ input = chunk_cata("cccc", ip->get_address(ip), chunk_from_thing(spi),
+ chunk_from_thing(t), secret);
+ hash = chunk_alloca(this->hasher->get_hash_size(this->hasher));
+ this->hasher->get_hash(this->hasher, input, hash.ptr);
+ return chunk_cat("cc", chunk_from_thing(t), hash);
+}
+
+/**
+ * verify a received cookie
+ */
+static bool cookie_verify(private_receiver_t *this, message_t *message,
+ chunk_t cookie)
+{
+ u_int32_t t, now;
+ chunk_t reference;
+ chunk_t secret;
+
+ now = time_monotonic(NULL);
+ t = *(u_int32_t*)cookie.ptr;
+
+ if (cookie.len != sizeof(u_int32_t) +
+ this->hasher->get_hash_size(this->hasher) ||
+ t < now - this->secret_offset - COOKIE_LIFETIME)
+ {
+ DBG2(DBG_NET, "received cookie lifetime expired, rejecting");
+ return FALSE;
+ }
+
+ /* check if cookie is derived from old_secret */
+ if (t + this->secret_offset > this->secret_switch)
+ {
+ secret = chunk_from_thing(this->secret);
+ }
+ else
+ {
+ secret = chunk_from_thing(this->secret_old);
+ }
+
+ /* compare own calculation against received */
+ reference = cookie_build(this, message, t, secret);
+ if (chunk_equals(reference, cookie))
+ {
+ chunk_free(&reference);
+ return TRUE;
+ }
+ chunk_free(&reference);
+ return FALSE;
+}
+
+/**
+ * check if cookies are required, and if so, a valid cookie is included
+ */
+static bool cookie_required(private_receiver_t *this, message_t *message)
+{
+ bool failed = FALSE;
+
+ if (charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
+ NULL) >= this->cookie_threshold)
+ {
+ /* check for a cookie. We don't use our parser here and do it
+ * quick and dirty for performance reasons.
+ * we assume the cookie is the first payload (which is a MUST), and
+ * the cookie's SPI length is zero. */
+ packet_t *packet = message->get_packet(message);
+ chunk_t data = packet->get_data(packet);
+ 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 ||
+ *(u_int16_t*)(data.ptr + IKE_HEADER_LENGTH + 6) != htons(COOKIE))
+ {
+ /* no cookie found */
+ failed = TRUE;
+ }
+ else
+ {
+ data.ptr += IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH;
+ data.len = sizeof(u_int32_t) + this->hasher->get_hash_size(this->hasher);
+ if (!cookie_verify(this, message, data))
+ {
+ DBG2(DBG_NET, "found cookie, but content invalid");
+ failed = TRUE;
+ }
+ }
+ packet->destroy(packet);
+ }
+ return failed;
+}
+
+/**
+ * check if peer has to many half open IKE_SAs
+ */
+static bool peer_to_aggressive(private_receiver_t *this, message_t *message)
+{
+ if (charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
+ message->get_source(message)) >= this->block_threshold)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Job callback to receive packets
+ */
+static job_requeue_t receive_packets(private_receiver_t *this)
+{
+ packet_t *packet;
+ message_t *message;
+ job_t *job;
+
+ /* read in a packet */
+ if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
+ {
+ DBG2(DBG_NET, "receiving from socket failed!");
+ return JOB_REQUEUE_FAIR;
+ }
+
+ /* parse message header */
+ message = message_create_from_packet(packet);
+ if (message->parse_header(message) != SUCCESS)
+ {
+ DBG1(DBG_NET, "received invalid IKE header from %H - ignored",
+ packet->get_source(packet));
+ message->destroy(message);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ /* check IKE major version */
+ if (message->get_major_version(message) != IKE_MAJOR_VERSION)
+ {
+ DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, "
+ "sending INVALID_MAJOR_VERSION", message->get_major_version(message),
+ message->get_minor_version(message), packet->get_source(packet));
+ send_notify(message, INVALID_MAJOR_VERSION, chunk_empty);
+ message->destroy(message);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ if (message->get_request(message) &&
+ message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ /* check for cookies */
+ if (this->cookie_threshold && cookie_required(this, message))
+ {
+ u_int32_t now = time_monotonic(NULL);
+ chunk_t cookie = cookie_build(this, message, now - this->secret_offset,
+ chunk_from_thing(this->secret));
+
+ DBG2(DBG_NET, "received packet from: %#H to %#H",
+ message->get_source(message),
+ message->get_destination(message));
+ DBG2(DBG_NET, "sending COOKIE notify to %H",
+ message->get_source(message));
+ send_notify(message, COOKIE, cookie);
+ chunk_free(&cookie);
+ if (++this->secret_used > COOKIE_REUSE)
+ {
+ /* create new cookie */
+ DBG1(DBG_NET, "generating new cookie secret after %d uses",
+ this->secret_used);
+ memcpy(this->secret_old, this->secret, SECRET_LENGTH);
+ this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
+ this->secret_switch = now;
+ this->secret_used = 0;
+ }
+ message->destroy(message);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ /* check if peer has not too many IKE_SAs half open */
+ if (this->block_threshold && peer_to_aggressive(this, message))
+ {
+ DBG1(DBG_NET, "ignoring IKE_SA setup from %H, "
+ "peer too aggressive", message->get_source(message));
+ message->destroy(message);
+ return JOB_REQUEUE_DIRECT;
+ }
+ }
+ job = (job_t*)process_message_job_create(message);
+ if (this->receive_delay)
+ {
+ charon->scheduler->schedule_job_ms(charon->scheduler,
+ job, this->receive_delay);
+ }
+ else
+ {
+ charon->processor->queue_job(charon->processor, job);
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(receiver_t, destroy, void,
+ private_receiver_t *this)
+{
+ this->job->cancel(this->job);
+ this->rng->destroy(this->rng);
+ this->hasher->destroy(this->hasher);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+receiver_t *receiver_create()
+{
+ private_receiver_t *this;
+ u_int32_t now = time_monotonic(NULL);
+
+ INIT(this,
+ .public.destroy = _destroy,
+ .secret_switch = now,
+ .secret_offset = random() % now,
+ );
+
+ if (lib->settings->get_bool(lib->settings, "charon.dos_protection", TRUE))
+ {
+ this->cookie_threshold = lib->settings->get_int(lib->settings,
+ "charon.cookie_threshold", COOKIE_THRESHOLD_DEFAULT);
+ this->block_threshold = lib->settings->get_int(lib->settings,
+ "charon.block_threshold", BLOCK_THRESHOLD_DEFAULT);
+ }
+ this->receive_delay = lib->settings->get_int(lib->settings,
+ "charon.receive_delay", 0);
+
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_NET, "creating cookie hasher failed, no hashers supported");
+ free(this);
+ return NULL;
+ }
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (this->rng == NULL)
+ {
+ DBG1(DBG_NET, "creating cookie RNG failed, no RNG supported");
+ this->hasher->destroy(this->hasher);
+ free(this);
+ return NULL;
+ }
+ this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
+ memcpy(this->secret_old, this->secret, SECRET_LENGTH);
+
+ this->job = callback_job_create((callback_job_cb_t)receive_packets,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/network/receiver.h b/src/libcharon/network/receiver.h
new file mode 100644
index 000000000..690d8dbab
--- /dev/null
+++ b/src/libcharon/network/receiver.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup receiver receiver
+ * @{ @ingroup network
+ */
+
+#ifndef RECEIVER_H_
+#define RECEIVER_H_
+
+typedef struct receiver_t receiver_t;
+
+#include <library.h>
+#include <utils/host.h>
+
+/**
+ * Receives packets from the socket and adds them to the job queue.
+ *
+ * The receiver starts a thread, wich reads on the blocking socket. A received
+ * packet is preparsed and a process_message_job is queued in the job queue.
+ *
+ * To endure DoS attacks, cookies are enabled when to many IKE_SAs are half
+ * open. The calculation of cookies is slightly different from the proposed
+ * method in RFC4306. We do not include a nonce, because we think the advantage
+ * we gain does not justify the overhead to parse the whole message.
+ * Instead of VersionIdOfSecret, we include a timestamp. This allows us to
+ * find out wich key was used for cookie creation. Further, we can set a
+ * lifetime for the cookie, which allows us to reuse the secret for a longer
+ * time.
+ * COOKIE = time | sha1( IPi | SPIi | time | secret )
+ *
+ * The secret is changed after a certain amount of cookies sent. The old
+ * secret is stored to allow a clean migration between secret changes.
+ *
+ * Further, the number of half-initiated IKE_SAs is limited per peer. This
+ * mades it impossible for a peer to flood the server with its real IP address.
+ */
+struct receiver_t {
+
+ /**
+ * Destroys a receiver_t object.
+ */
+ void (*destroy) (receiver_t *receiver);
+};
+
+/**
+ * Create a receiver_t object.
+ *
+ * The receiver thread will start working, get data
+ * from the socket and add those packets to the job queue.
+ *
+ * @return receiver_t object, NULL if initialization fails
+ */
+receiver_t * receiver_create(void);
+
+#endif /** RECEIVER_H_ @}*/
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
new file mode 100644
index 000000000..c18f1138e
--- /dev/null
+++ b/src/libcharon/network/sender.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "sender.h"
+
+#include <daemon.h>
+#include <network/socket.h>
+#include <processing/jobs/callback_job.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+
+typedef struct private_sender_t private_sender_t;
+
+/**
+ * Private data of a sender_t object.
+ */
+struct private_sender_t {
+ /**
+ * Public part of a sender_t object.
+ */
+ sender_t public;
+
+ /**
+ * Sender threads job.
+ */
+ callback_job_t *job;
+
+ /**
+ * The packets are stored in a linked list
+ */
+ linked_list_t *list;
+
+ /**
+ * mutex to synchronize access to list
+ */
+ mutex_t *mutex;
+
+ /**
+ * condvar to signal for packets added to list
+ */
+ condvar_t *got;
+
+ /**
+ * condvar to signal for packets sent
+ */
+ condvar_t *sent;
+
+ /**
+ * Delay for sending outgoing packets, to simulate larger RTT
+ */
+ int send_delay;
+};
+
+METHOD(sender_t, send_, void,
+ private_sender_t *this, packet_t *packet)
+{
+ host_t *src, *dst;
+
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+ if (this->send_delay)
+ {
+ usleep(this->send_delay * 1000);
+ }
+
+ this->mutex->lock(this->mutex);
+ this->list->insert_last(this->list, packet);
+ this->got->signal(this->got);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Job callback function to send packets
+ */
+static job_requeue_t send_packets(private_sender_t * this)
+{
+ packet_t *packet;
+ bool oldstate;
+
+ this->mutex->lock(this->mutex);
+ while (this->list->get_count(this->list) == 0)
+ {
+ /* add cleanup handler, wait for packet, remove cleanup handler */
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ oldstate = thread_cancelability(TRUE);
+
+ this->got->wait(this->got, this->mutex);
+
+ thread_cancelability(oldstate);
+ thread_cleanup_pop(FALSE);
+ }
+ this->list->remove_first(this->list, (void**)&packet);
+ this->sent->signal(this->sent);
+ this->mutex->unlock(this->mutex);
+
+ charon->socket->send(charon->socket, packet);
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(sender_t, destroy, void,
+ private_sender_t *this)
+{
+ /* send all packets in the queue */
+ this->mutex->lock(this->mutex);
+ while (this->list->get_count(this->list))
+ {
+ this->sent->wait(this->sent, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+ this->job->cancel(this->job);
+ this->list->destroy(this->list);
+ this->got->destroy(this->got);
+ this->sent->destroy(this->sent);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+sender_t * sender_create()
+{
+ private_sender_t *this;
+
+ INIT(this,
+ .public = {
+ .send = _send_,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .got = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .sent = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .job = callback_job_create((callback_job_cb_t)send_packets,
+ this, NULL, NULL),
+ .send_delay = lib->settings->get_int(lib->settings,
+ "charon.send_delay", 0),
+ );
+
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h
new file mode 100644
index 000000000..f77fadab2
--- /dev/null
+++ b/src/libcharon/network/sender.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup sender sender
+ * @{ @ingroup network
+ */
+
+#ifndef SENDER_H_
+#define SENDER_H_
+
+typedef struct sender_t sender_t;
+
+#include <library.h>
+#include <network/packet.h>
+
+/**
+ * Thread responsible for sending packets over the socket.
+ */
+struct sender_t {
+
+ /**
+ * Send a packet over the network.
+ *
+ * This function is non blocking and adds the packet to a queue.
+ * Whenever the sender thread thinks it's good to send the packet,
+ * it'll do so.
+ *
+ * @param packet packet to send
+ */
+ void (*send) (sender_t *this, packet_t *packet);
+
+ /**
+ * Destroys a sender object.
+ */
+ void (*destroy) (sender_t *this);
+};
+
+/**
+ * Create the sender thread.
+ *
+ * The thread will start to work, getting packets
+ * from its queue and sends them out.
+ *
+ * @return created sender object
+ */
+sender_t * sender_create(void);
+
+#endif /** SENDER_H_ @}*/
diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h
new file mode 100644
index 000000000..5c5a4edfb
--- /dev/null
+++ b/src/libcharon/network/socket.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket socket
+ * @{ @ingroup network
+ */
+
+#ifndef SOCKET_H_
+#define SOCKET_H_
+
+typedef struct socket_t socket_t;
+
+#include <library.h>
+#include <network/packet.h>
+#include <utils/enumerator.h>
+
+/**
+ * Socket interface definition.
+ */
+struct socket_t {
+
+ /**
+ * Receive a packet.
+ *
+ * Reads a packet from the socket and sets source/dest
+ * appropriately.
+ *
+ * @param packet pinter gets address from allocated packet_t
+ * @return
+ * - SUCCESS when packet successfully received
+ * - FAILED when unable to receive
+ */
+ status_t (*receive) (socket_t *this, packet_t **packet);
+
+ /**
+ * Send a packet.
+ *
+ * Sends a packet to the net using source and destination addresses of
+ * the packet.
+ *
+ * @param packet packet_t to send
+ * @return
+ * - SUCCESS when packet successfully sent
+ * - FAILED when unable to send
+ */
+ status_t (*send) (socket_t *this, packet_t *packet);
+};
+
+#endif /** SOCKET_H_ @}*/
diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c
new file mode 100644
index 000000000..0dbce4b1b
--- /dev/null
+++ b/src/libcharon/network/socket_manager.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "socket_manager.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+typedef struct private_socket_manager_t private_socket_manager_t;
+
+/**
+ * Private data of an socket_manager_t object.
+ */
+struct private_socket_manager_t {
+
+ /**
+ * Public socket_manager_t interface.
+ */
+ socket_manager_t public;
+
+ /**
+ * List of registered socket
+ */
+ linked_list_t *sockets;
+
+ /**
+ * Lock for sockets list
+ */
+ rwlock_t *lock;
+};
+
+METHOD(socket_manager_t, receiver, status_t,
+ private_socket_manager_t *this, packet_t **packet)
+{
+ socket_t *socket;
+ status_t status;
+
+ this->lock->read_lock(this->lock);
+ if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS)
+ {
+ DBG1(DBG_NET, "no socket implementation registered, receiving failed");
+ this->lock->unlock(this->lock);
+ return NOT_SUPPORTED;
+ }
+ /* receive is blocking and the thread can be cancelled */
+ thread_cleanup_push((thread_cleanup_t)this->lock->unlock, this->lock);
+ status = socket->receive(socket, packet);
+ thread_cleanup_pop(TRUE);
+ return status;
+}
+
+METHOD(socket_manager_t, sender, status_t,
+ private_socket_manager_t *this, packet_t *packet)
+{
+ socket_t *socket;
+ status_t status;
+
+ this->lock->read_lock(this->lock);
+ if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS)
+ {
+ DBG1(DBG_NET, "no socket implementation registered, sending failed");
+ this->lock->unlock(this->lock);
+ return NOT_SUPPORTED;
+ }
+ status = socket->send(socket, packet);
+ this->lock->unlock(this->lock);
+ return status;
+}
+
+METHOD(socket_manager_t, add_socket, void,
+ private_socket_manager_t *this, socket_t *socket)
+{
+ this->lock->write_lock(this->lock);
+ this->sockets->insert_last(this->sockets, socket);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(socket_manager_t, remove_socket, void,
+ private_socket_manager_t *this, socket_t *socket)
+{
+ this->lock->write_lock(this->lock);
+ this->sockets->remove(this->sockets, socket, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(socket_manager_t, destroy, void,
+ private_socket_manager_t *this)
+{
+ this->sockets->destroy(this->sockets);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * See header
+ */
+socket_manager_t *socket_manager_create()
+{
+ private_socket_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .send = _sender,
+ .receive = _receiver,
+ .add_socket = _add_socket,
+ .remove_socket = _remove_socket,
+ .destroy = _destroy,
+ },
+ .sockets = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h
new file mode 100644
index 000000000..b33d5c71c
--- /dev/null
+++ b/src/libcharon/network/socket_manager.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_manager socket_manager
+ * @{ @ingroup network
+ */
+
+#ifndef SOCKET_MANAGER_H_
+#define SOCKET_MANAGER_H_
+
+#include <network/socket.h>
+
+typedef struct socket_manager_t socket_manager_t;
+
+/**
+ * Handle pluggable socket implementations and send/receive packets through it.
+ */
+struct socket_manager_t {
+
+ /**
+ * Receive a packet using the registered socket.
+ *
+ * @param packet allocated packet that has been received
+ * @return
+ * - SUCCESS when packet successfully received
+ * - FAILED when unable to receive
+ */
+ status_t (*receive) (socket_manager_t *this, packet_t **packet);
+
+ /**
+ * Send a packet using the registered socket.
+ *
+ * @param packet packet to send out
+ * @return
+ * - SUCCESS when packet successfully sent
+ * - FAILED when unable to send
+ */
+ status_t (*send) (socket_manager_t *this, packet_t *packet);
+
+ /**
+ * Register a socket implementation.
+ */
+ void (*add_socket)(socket_manager_t *this, socket_t *socket);
+
+ /**
+ * Unregister a registered socket implementation.
+ */
+ void (*remove_socket)(socket_manager_t *this, socket_t *socket);
+
+ /**
+ * Destroy a socket_manager_t.
+ */
+ void (*destroy)(socket_manager_t *this);
+};
+
+/**
+ * Create a socket_manager instance.
+ */
+socket_manager_t *socket_manager_create();
+
+#endif /** SOCKET_MANAGER_H_ @}*/
diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am
new file mode 100644
index 000000000..e8423589c
--- /dev/null
+++ b/src/libcharon/plugins/android/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-android.la
+else
+plugin_LTLIBRARIES = libstrongswan-android.la
+endif
+
+libstrongswan_android_la_SOURCES = \
+ android_plugin.c android_plugin.h \
+ android_handler.c android_handler.h
+
+libstrongswan_android_la_LDFLAGS = -module -avoid-version
+libstrongswan_android_la_LIBADD = -lcutils
diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in
new file mode 100644
index 000000000..9f12a9c75
--- /dev/null
+++ b/src/libcharon/plugins/android/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/android
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_android_la_DEPENDENCIES =
+am_libstrongswan_android_la_OBJECTS = android_plugin.lo \
+ android_handler.lo
+libstrongswan_android_la_OBJECTS = \
+ $(am_libstrongswan_android_la_OBJECTS)
+libstrongswan_android_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_android_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_android_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_android_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_android_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_android_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-android.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android.la
+libstrongswan_android_la_SOURCES = \
+ android_plugin.c android_plugin.h \
+ android_handler.c android_handler.h
+
+libstrongswan_android_la_LDFLAGS = -module -avoid-version
+libstrongswan_android_la_LIBADD = -lcutils
+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/android/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/android/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-android.la: $(libstrongswan_android_la_OBJECTS) $(libstrongswan_android_la_DEPENDENCIES)
+ $(libstrongswan_android_la_LINK) $(am_libstrongswan_android_la_rpath) $(libstrongswan_android_la_OBJECTS) $(libstrongswan_android_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
new file mode 100644
index 000000000..a475eeaab
--- /dev/null
+++ b/src/libcharon/plugins/android/android_handler.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "android_handler.h"
+
+#include <utils/linked_list.h>
+
+#include <cutils/properties.h>
+
+typedef struct private_android_handler_t private_android_handler_t;
+
+/**
+ * Private data of an android_handler_t object.
+ */
+struct private_android_handler_t {
+
+ /**
+ * Public android_handler_t interface.
+ */
+ android_handler_t public;
+
+ /**
+ * List of registered DNS servers
+ */
+ linked_list_t *dns;
+};
+
+/**
+ * Struct to store a pair of old and installed DNS servers
+ */
+typedef struct {
+ /** installed dns server */
+ host_t *dns;
+ /** old dns server */
+ host_t *old;
+} dns_pair_t;
+
+/**
+ * Destroy a pair of old and installed DNS servers
+ */
+void destroy_dns_pair(dns_pair_t *this)
+{
+ DESTROY_IF(this->dns);
+ DESTROY_IF(this->old);
+ free(this);
+}
+
+/**
+ * Filter pairs of DNS servers
+ */
+bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out)
+{
+ *out = (*in)->dns;
+ return TRUE;
+}
+
+/**
+ * Read DNS server property with a given index
+ */
+host_t *get_dns_server(int index)
+{
+ host_t *dns = NULL;
+ char key[10], value[PROPERTY_VALUE_MAX];
+
+ if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key))
+ {
+ return NULL;
+ }
+
+ if (property_get(key, value, NULL) > 0)
+ {
+ dns = host_create_from_string(value, 0);
+ }
+ return dns;
+}
+
+/**
+ * Set DNS server property with a given index
+ */
+bool set_dns_server(int index, host_t *dns)
+{
+ char key[10], value[PROPERTY_VALUE_MAX];
+
+ if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key))
+ {
+ return FALSE;
+ }
+
+ if (dns)
+ {
+ if (snprintf(value, sizeof(value), "%H", dns) >= sizeof(value))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ value[0] = '\0';
+ }
+
+ if (property_set(key, value) != 0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_android_handler_t *this, identification_t *id,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ {
+ host_t *dns;
+ dns_pair_t *pair;
+ int index;
+
+ dns = host_create_from_chunk(AF_INET, data, 0);
+ if (dns)
+ {
+ pair = malloc_thing(dns_pair_t);
+ pair->dns = dns;
+ index = this->dns->get_count(this->dns) + 1;
+ pair->old = get_dns_server(index);
+ set_dns_server(index, dns);
+ this->dns->insert_last(this->dns, pair);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ default:
+ return FALSE;
+ }
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_android_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ if (type == INTERNAL_IP4_DNS)
+ {
+ enumerator_t *enumerator;
+ dns_pair_t *pair;
+ int index;
+
+ enumerator = this->dns->create_enumerator(this->dns);
+ for (index = 1; enumerator->enumerate(enumerator, &pair); index++)
+ {
+ if (chunk_equals(pair->dns->get_address(pair->dns), data))
+ {
+ this->dns->remove_at(this->dns, enumerator);
+ set_dns_server(index, pair->old);
+ destroy_dns_pair(pair);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+METHOD(enumerator_t, enumerate_dns, bool,
+ enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data)
+{
+ *type = INTERNAL_IP4_DNS;
+ *data = chunk_empty;
+ /* stop enumeration */
+ this->enumerate = (void*)return_false;
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+ android_handler_t *this, identification_t *id, host_t *vip)
+{
+ enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .enumerate = (void*)_enumerate_dns,
+ .destroy = (void*)free,
+ );
+ return enumerator;
+}
+
+METHOD(android_handler_t, destroy, void,
+ private_android_handler_t *this)
+{
+ this->dns->destroy_function(this->dns, (void*)destroy_dns_pair);
+ free(this);
+}
+
+/**
+ * See header
+ */
+android_handler_t *android_handler_create()
+{
+ private_android_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .destroy = _destroy,
+ },
+ .dns = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/android/android_handler.h b/src/libcharon/plugins/android/android_handler.h
new file mode 100644
index 000000000..af620505b
--- /dev/null
+++ b/src/libcharon/plugins/android/android_handler.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_handler android_handler
+ * @{ @ingroup android
+ */
+
+#ifndef ANDROID_HANDLER_H_
+#define ANDROID_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct android_handler_t android_handler_t;
+
+/**
+ * Android specific DNS attribute handler.
+ */
+struct android_handler_t {
+
+ /**
+ * Implements attribute_handler_t.
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Destroy a android_handler_t.
+ */
+ void (*destroy)(android_handler_t *this);
+};
+
+/**
+ * Create a android_handler instance.
+ */
+android_handler_t *android_handler_create();
+
+#endif /** ANDROID_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c
new file mode 100644
index 000000000..9a558f53b
--- /dev/null
+++ b/src/libcharon/plugins/android/android_plugin.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 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 "android_plugin.h"
+#include "android_handler.h"
+
+#include <hydra.h>
+#include <daemon.h>
+
+typedef struct private_android_plugin_t private_android_plugin_t;
+
+/**
+ * Private data of an android_plugin_t object.
+ */
+struct private_android_plugin_t {
+
+ /**
+ * Public android_plugin_t interface.
+ */
+ android_plugin_t public;
+
+ /**
+ * Android specific DNS handler
+ */
+ android_handler_t *handler;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_android_plugin_t *this)
+{
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ this->handler->destroy(this->handler);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *android_plugin_create()
+{
+ private_android_plugin_t *this;
+
+ INIT(this,
+ .public.plugin = {
+ .destroy = _destroy,
+ },
+ .handler = android_handler_create(),
+ );
+
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/android/android_plugin.h b/src/libcharon/plugins/android/android_plugin.h
new file mode 100644
index 000000000..987f2aa37
--- /dev/null
+++ b/src/libcharon/plugins/android/android_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 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 android android
+ * @ingroup cplugins
+ *
+ * @defgroup android_plugin android_plugin
+ * @{ @ingroup android
+ */
+
+#ifndef ANDROID_PLUGIN_H_
+#define ANDROID_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct android_plugin_t android_plugin_t;
+
+/**
+ * Plugin providing functionality specific to the Android platform.
+ */
+struct android_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** ANDROID_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/dhcp/Makefile.am b/src/libcharon/plugins/dhcp/Makefile.am
new file mode 100644
index 000000000..45d7536be
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-dhcp.la
+else
+plugin_LTLIBRARIES = libstrongswan-dhcp.la
+endif
+
+libstrongswan_dhcp_la_SOURCES = dhcp_plugin.h dhcp_plugin.c \
+ dhcp_provider.h dhcp_provider.c \
+ dhcp_socket.h dhcp_socket.c \
+ dhcp_transaction.h dhcp_transaction.c
+
+libstrongswan_dhcp_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
new file mode 100644
index 000000000..7606b963c
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/dhcp
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_dhcp_la_LIBADD =
+am_libstrongswan_dhcp_la_OBJECTS = dhcp_plugin.lo dhcp_provider.lo \
+ dhcp_socket.lo dhcp_transaction.lo
+libstrongswan_dhcp_la_OBJECTS = $(am_libstrongswan_dhcp_la_OBJECTS)
+libstrongswan_dhcp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_dhcp_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_dhcp_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_dhcp_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_dhcp_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_dhcp_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-dhcp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-dhcp.la
+libstrongswan_dhcp_la_SOURCES = dhcp_plugin.h dhcp_plugin.c \
+ dhcp_provider.h dhcp_provider.c \
+ dhcp_socket.h dhcp_socket.c \
+ dhcp_transaction.h dhcp_transaction.c
+
+libstrongswan_dhcp_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/dhcp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/dhcp/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-dhcp.la: $(libstrongswan_dhcp_la_OBJECTS) $(libstrongswan_dhcp_la_DEPENDENCIES)
+ $(libstrongswan_dhcp_la_LINK) $(am_libstrongswan_dhcp_la_rpath) $(libstrongswan_dhcp_la_OBJECTS) $(libstrongswan_dhcp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcp_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcp_provider.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcp_socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcp_transaction.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.c b/src/libcharon/plugins/dhcp/dhcp_plugin.c
new file mode 100644
index 000000000..829fd6356
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_plugin.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "dhcp_plugin.h"
+
+#include <hydra.h>
+#include <daemon.h>
+
+#include "dhcp_socket.h"
+#include "dhcp_provider.h"
+
+typedef struct private_dhcp_plugin_t private_dhcp_plugin_t;
+
+/**
+ * private data of dhcp plugin
+ */
+struct private_dhcp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ dhcp_plugin_t public;
+
+ /**
+ * DHCP communication socket
+ */
+ dhcp_socket_t *socket;
+
+ /**
+ * Attribute provider
+ */
+ dhcp_provider_t *provider;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_dhcp_plugin_t *this)
+{
+ hydra->attributes->remove_provider(hydra->attributes,
+ &this->provider->provider);
+ this->provider->destroy(this->provider);
+ this->socket->destroy(this->socket);
+ free(this);
+}
+
+/**
+ * Plugin constructor.
+ */
+plugin_t *dhcp_plugin_create()
+{
+ private_dhcp_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .socket = dhcp_socket_create(),
+ );
+
+ if (!this->socket)
+ {
+ free(this);
+ return NULL;
+ }
+
+ this->provider = dhcp_provider_create(this->socket);
+ hydra->attributes->add_provider(hydra->attributes,
+ &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.h b/src/libcharon/plugins/dhcp/dhcp_plugin.h
new file mode 100644
index 000000000..b21b44d28
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup dhcp dhcp
+ * @ingroup cplugins
+ *
+ * @defgroup dhcp_plugin dhcp_plugin
+ * @{ @ingroup dhcp
+ */
+
+#ifndef DHCP_PLUGIN_H_
+#define DHCP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct dhcp_plugin_t dhcp_plugin_t;
+
+/**
+ * DHCP based attribute provider plugin.
+ */
+struct dhcp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** DHCP_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
new file mode 100644
index 000000000..dbcceb6ce
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "dhcp_provider.h"
+
+#include <utils/hashtable.h>
+#include <threading/mutex.h>
+
+typedef struct private_dhcp_provider_t private_dhcp_provider_t;
+
+/**
+ * Private data of an dhcp_provider_t object.
+ */
+struct private_dhcp_provider_t {
+
+ /**
+ * Public dhcp_provider_t interface.
+ */
+ dhcp_provider_t public;
+
+ /**
+ * Completed DHCP transactions
+ */
+ hashtable_t *transactions;
+
+ /**
+ * Lock for transactions
+ */
+ mutex_t *mutex;
+
+ /**
+ * DHCP communication socket
+ */
+ dhcp_socket_t *socket;
+};
+
+/**
+ * Hashtable hash function
+ */
+static u_int hash(void *key)
+{
+ return (uintptr_t)key;
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(void *a, void *b)
+{
+ return a == b;
+}
+
+/**
+ * Hash ID and host to a key
+ */
+static uintptr_t hash_id_host(identification_t *id, host_t *host)
+{
+ return chunk_hash_inc(id->get_encoding(id),
+ chunk_hash(host->get_address(host)));
+}
+
+/**
+ * Hash a DHCP transaction to a key, using address and id
+ */
+static uintptr_t hash_transaction(dhcp_transaction_t *transaction)
+{
+ return hash_id_host(transaction->get_identity(transaction),
+ transaction->get_address(transaction));
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_dhcp_provider_t *this, char *pool,
+ identification_t *id, host_t *requested)
+{
+ if (streq(pool, "dhcp"))
+ {
+ dhcp_transaction_t *transaction, *old;
+ host_t *vip;
+
+ transaction = this->socket->enroll(this->socket, id);
+ if (!transaction)
+ {
+ return NULL;
+ }
+ vip = transaction->get_address(transaction);
+ vip = vip->clone(vip);
+ this->mutex->lock(this->mutex);
+ old = this->transactions->put(this->transactions,
+ (void*)hash_transaction(transaction), transaction);
+ this->mutex->unlock(this->mutex);
+ DESTROY_IF(old);
+ return vip;
+ }
+ return NULL;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+ private_dhcp_provider_t *this, char *pool,
+ host_t *address, identification_t *id)
+{
+ if (streq(pool, "dhcp"))
+ {
+ dhcp_transaction_t *transaction;
+
+ this->mutex->lock(this->mutex);
+ transaction = this->transactions->remove(this->transactions,
+ (void*)hash_id_host(id, address));
+ this->mutex->unlock(this->mutex);
+ if (transaction)
+ {
+ this->socket->release(this->socket, transaction);
+ transaction->destroy(transaction);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_dhcp_provider_t *this, identification_t *id, host_t *vip)
+{
+ dhcp_transaction_t *transaction;
+
+ if (!vip)
+ {
+ return NULL;
+ }
+ this->mutex->lock(this->mutex);
+ transaction = this->transactions->get(this->transactions,
+ (void*)hash_id_host(id, vip));
+ if (!transaction)
+ {
+ this->mutex->unlock(this->mutex);
+ return NULL;
+ }
+ return enumerator_create_cleaner(
+ transaction->create_attribute_enumerator(transaction),
+ (void*)this->mutex->unlock, this->mutex);
+}
+
+METHOD(dhcp_provider_t, destroy, void,
+ private_dhcp_provider_t *this)
+{
+ enumerator_t *enumerator;
+ dhcp_transaction_t *value;
+ void *key;
+
+ enumerator = this->transactions->create_enumerator(this->transactions);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ value->destroy(value);
+ }
+ enumerator->destroy(enumerator);
+ this->transactions->destroy(this->transactions);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+dhcp_provider_t *dhcp_provider_create(dhcp_socket_t *socket)
+{
+ private_dhcp_provider_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .destroy = _destroy,
+ },
+ .socket = socket,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .transactions = hashtable_create(hash, equals, 8),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.h b/src/libcharon/plugins/dhcp/dhcp_provider.h
new file mode 100644
index 000000000..e720e876c
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup dhcp_provider dhcp_provider
+ * @{ @ingroup dhcp
+ */
+
+#ifndef DHCP_PROVIDER_H_
+#define DHCP_PROVIDER_H_
+
+typedef struct dhcp_provider_t dhcp_provider_t;
+
+#include "dhcp_socket.h"
+
+#include <attributes/attribute_provider.h>
+
+/**
+ * DHCP based attribute provider.
+ */
+struct dhcp_provider_t {
+
+ /**
+ * Implements attribute_provier_t interface.
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Destroy a dhcp_provider_t.
+ */
+ void (*destroy)(dhcp_provider_t *this);
+};
+
+/**
+ * Create a dhcp_provider instance.
+ *
+ * @param socket socket to use for DHCP communication
+ * @return provider instance
+ */
+dhcp_provider_t *dhcp_provider_create(dhcp_socket_t *socket);
+
+#endif /** DHCP_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c
new file mode 100644
index 000000000..f61b3a60e
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "dhcp_socket.h"
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/filter.h>
+
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/thread.h>
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+#define DHCP_SERVER_PORT 67
+#define DHCP_CLIENT_PORT 68
+#define DHCP_TRIES 5
+
+typedef struct private_dhcp_socket_t private_dhcp_socket_t;
+
+/**
+ * Private data of an dhcp_socket_t object.
+ */
+struct private_dhcp_socket_t {
+
+ /**
+ * Public dhcp_socket_t interface.
+ */
+ dhcp_socket_t public;
+
+ /**
+ * Random number generator
+ */
+ rng_t *rng;
+
+ /**
+ * List of transactions in DISCOVER
+ */
+ linked_list_t *discover;
+
+ /**
+ * List of transactions in REQUEST
+ */
+ linked_list_t *request;
+
+ /**
+ * List of successfully completed transactions
+ */
+ linked_list_t *completed;
+
+ /**
+ * Lock for transactions
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to wait for transaction completion
+ */
+ condvar_t *condvar;
+
+ /**
+ * Threads waiting in condvar
+ */
+ int waiting;
+
+ /**
+ * DHCP send socket
+ */
+ int send;
+
+ /**
+ * DHCP receive socket
+ */
+ int receive;
+
+ /**
+ * Do we use per-identity or random leases (and MAC addresses)
+ */
+ bool identity_lease;
+
+ /**
+ * DHCP server address, or broadcast
+ */
+ host_t *dst;
+
+ /**
+ * Callback job receiving DHCP responses
+ */
+ callback_job_t *job;
+};
+
+/**
+ * DHCP opcode (or BOOTP actually)
+ */
+typedef enum {
+ BOOTREQUEST = 1,
+ BOOTREPLY = 2,
+} dhcp_opcode_t;
+
+/**
+ * Some DHCP options used
+ */
+typedef enum {
+ DHCP_DNS_SERVER = 6,
+ DHCP_HOST_NAME = 12,
+ DHCP_NBNS_SERVER = 44,
+ DHCP_REQUESTED_IP = 50,
+ DHCP_MESSAGE_TYPE = 53,
+ DHCP_SERVER_ID = 54,
+ DHCP_PARAM_REQ_LIST = 55,
+ DHCP_CLIENT_ID = 61,
+ DHCP_OPTEND = 255,
+} dhcp_option_type_t;
+
+/**
+ * DHCP messages types in the DHCP_MESSAGE_TYPE option
+ */
+typedef enum {
+ DHCP_DISCOVER = 1,
+ DHCP_OFFER = 2,
+ DHCP_REQUEST = 3,
+ DHCP_DECLINE = 4,
+ DHCP_ACK = 5,
+ DHCP_NAK = 6,
+ DHCP_RELEASE = 7,
+ DHCP_INFORM = 8,
+} dhcp_message_type_t;
+/**
+ * DHCP option encoding, a TLV
+ */
+typedef struct __attribute__((packed)) {
+ u_int8_t type;
+ u_int8_t len;
+ char data[];
+} dhcp_option_t;
+
+/**
+ * DHCP message format, with a maximum size options buffer
+ */
+typedef struct __attribute__((packed)) {
+ u_int8_t opcode;
+ u_int8_t hw_type;
+ u_int8_t hw_addr_len;
+ u_int8_t hop_count;
+ u_int32_t transaction_id;
+ u_int16_t number_of_seconds;
+ u_int16_t flags;
+ u_int32_t client_address;
+ u_int32_t your_address;
+ u_int32_t server_address;
+ u_int32_t gateway_address;
+ char client_hw_addr[6];
+ char client_hw_padding[10];
+ char server_hostname[64];
+ char boot_filename[128];
+ u_int32_t magic_cookie;
+ char options[252];
+} dhcp_t;
+
+/**
+ * Prepare a DHCP message for a given transaction
+ */
+static int prepare_dhcp(private_dhcp_socket_t *this,
+ dhcp_transaction_t *transaction,
+ dhcp_message_type_t type, dhcp_t *dhcp)
+{
+ chunk_t chunk, broadcast = chunk_from_chars(0xFF,0xFF,0xFF,0xFF);
+ identification_t *identity;
+ dhcp_option_t *option;
+ int optlen = 0;
+ host_t *src;
+ u_int32_t id;
+
+ memset(dhcp, 0, sizeof(*dhcp));
+ dhcp->opcode = BOOTREQUEST;
+ dhcp->hw_type = ARPHRD_ETHER;
+ dhcp->hw_addr_len = 6;
+ dhcp->transaction_id = transaction->get_id(transaction);
+ if (chunk_equals(broadcast, this->dst->get_address(this->dst)))
+ {
+ /* TODO: send with 0.0.0.0 source address */
+ }
+ else
+ {
+ /* act as relay agent */
+ src = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, this->dst, NULL);
+ if (src)
+ {
+ memcpy(&dhcp->gateway_address, src->get_address(src).ptr,
+ sizeof(dhcp->gateway_address));
+ src->destroy(src);
+ }
+ }
+
+ identity = transaction->get_identity(transaction);
+ chunk = identity->get_encoding(identity);
+ /* magic bytes, a locally administered unicast MAC */
+ dhcp->client_hw_addr[0] = 0x7A;
+ dhcp->client_hw_addr[1] = 0xA7;
+ /* with ID specific postfix */
+ if (this->identity_lease)
+ {
+ id = htonl(chunk_hash(chunk));
+ }
+ else
+ {
+ id = transaction->get_id(transaction);
+ }
+ memcpy(&dhcp->client_hw_addr[2], &id, sizeof(id));
+
+ dhcp->magic_cookie = htonl(0x63825363);
+
+ option = (dhcp_option_t*)&dhcp->options[optlen];
+ option->type = DHCP_MESSAGE_TYPE;
+ option->len = 1;
+ option->data[0] = type;
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ if (identity->get_type(identity) == ID_FQDN)
+ {
+ option = (dhcp_option_t*)&dhcp->options[optlen];
+ option->type = DHCP_HOST_NAME;
+ option->len = min(chunk.len, 64);
+ memcpy(option->data, chunk.ptr, option->len);
+ optlen += sizeof(dhcp_option_t) + option->len;
+ }
+
+ option = (dhcp_option_t*)&dhcp->options[optlen];
+ option->type = DHCP_CLIENT_ID;
+ option->len = min(chunk.len, 64);
+ memcpy(option->data, chunk.ptr, option->len);
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ return optlen;
+}
+
+/**
+ * Send a DHCP message with given options length
+ */
+static bool send_dhcp(private_dhcp_socket_t *this,
+ dhcp_transaction_t *transaction, dhcp_t *dhcp, int optlen)
+{
+ host_t *dst;
+ ssize_t len;
+
+ dst = transaction->get_server(transaction);
+ if (!dst)
+ {
+ dst = this->dst;
+ }
+ len = offsetof(dhcp_t, magic_cookie) + ((optlen + 4) / 64 * 64 + 64);
+ return sendto(this->send, dhcp, len, 0, dst->get_sockaddr(dst),
+ *dst->get_sockaddr_len(dst)) == len;
+}
+
+/**
+ * Send DHCP discover using a given transaction
+ */
+static bool discover(private_dhcp_socket_t *this,
+ dhcp_transaction_t *transaction)
+{
+ dhcp_option_t *option;
+ dhcp_t dhcp;
+ int optlen;
+
+ optlen = prepare_dhcp(this, transaction, DHCP_DISCOVER, &dhcp);
+
+ DBG1(DBG_CFG, "sending DHCP DISCOVER to %H", this->dst);
+
+ option = (dhcp_option_t*)&dhcp.options[optlen];
+ option->type = DHCP_PARAM_REQ_LIST;
+ option->len = 2;
+ option->data[0] = DHCP_DNS_SERVER;
+ option->data[1] = DHCP_NBNS_SERVER;
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ dhcp.options[optlen++] = DHCP_OPTEND;
+
+ if (!send_dhcp(this, transaction, &dhcp, optlen))
+ {
+ DBG1(DBG_CFG, "sending DHCP DISCOVER failed: %s", strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Send DHCP request using a given transaction
+ */
+static bool request(private_dhcp_socket_t *this,
+ dhcp_transaction_t *transaction)
+{
+ dhcp_option_t *option;
+ dhcp_t dhcp;
+ host_t *offer, *server;
+ chunk_t chunk;
+ int optlen;
+
+ optlen = prepare_dhcp(this, transaction, DHCP_REQUEST, &dhcp);
+
+ offer = transaction->get_address(transaction);
+ server = transaction->get_server(transaction);
+ if (!offer || !server)
+ {
+ return FALSE;
+ }
+ DBG1(DBG_CFG, "sending DHCP REQUEST for %H to %H", offer, server);
+
+ option = (dhcp_option_t*)&dhcp.options[optlen];
+ option->type = DHCP_REQUESTED_IP;
+ option->len = 4;
+ chunk = offer->get_address(offer);
+ memcpy(option->data, chunk.ptr, min(chunk.len, option->len));
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ option = (dhcp_option_t*)&dhcp.options[optlen];
+ option->type = DHCP_SERVER_ID;
+ option->len = 4;
+ chunk = server->get_address(server);
+ memcpy(option->data, chunk.ptr, min(chunk.len, option->len));
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ option = (dhcp_option_t*)&dhcp.options[optlen];
+ option->type = DHCP_PARAM_REQ_LIST;
+ option->len = 2;
+ option->data[0] = DHCP_DNS_SERVER;
+ option->data[1] = DHCP_NBNS_SERVER;
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ dhcp.options[optlen++] = DHCP_OPTEND;
+
+ if (!send_dhcp(this, transaction, &dhcp, optlen))
+ {
+ DBG1(DBG_CFG, "sending DHCP REQUEST failed: %s", strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(dhcp_socket_t, enroll, dhcp_transaction_t*,
+ private_dhcp_socket_t *this, identification_t *identity)
+{
+ dhcp_transaction_t *transaction;
+ u_int32_t id;
+ int try;
+
+ this->rng->get_bytes(this->rng, sizeof(id), (u_int8_t*)&id);
+ transaction = dhcp_transaction_create(id, identity);
+
+ this->mutex->lock(this->mutex);
+ this->discover->insert_last(this->discover, transaction);
+ try = 1;
+ while (try <= DHCP_TRIES && discover(this, transaction))
+ {
+ if (!this->condvar->timed_wait(this->condvar, this->mutex, 1000 * try) &&
+ this->request->find_first(this->request, NULL,
+ (void**)&transaction) == SUCCESS)
+ {
+ break;
+ }
+ try++;
+ }
+ if (this->discover->remove(this->discover, transaction, NULL))
+ { /* no OFFER received */
+ this->mutex->unlock(this->mutex);
+ transaction->destroy(transaction);
+ DBG1(DBG_CFG, "DHCP DISCOVER timed out");
+ return NULL;
+ }
+
+ try = 1;
+ while (try <= DHCP_TRIES && request(this, transaction))
+ {
+ if (!this->condvar->timed_wait(this->condvar, this->mutex, 1000 * try) &&
+ this->completed->remove(this->completed, transaction, NULL))
+ {
+ break;
+ }
+ try++;
+ }
+ if (this->request->remove(this->request, transaction, NULL))
+ { /* no ACK received */
+ this->mutex->unlock(this->mutex);
+ transaction->destroy(transaction);
+ DBG1(DBG_CFG, "DHCP REQUEST timed out");
+ return NULL;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return transaction;
+}
+
+METHOD(dhcp_socket_t, release, void,
+ private_dhcp_socket_t *this, dhcp_transaction_t *transaction)
+{
+ dhcp_option_t *option;
+ dhcp_t dhcp;
+ host_t *release, *server;
+ chunk_t chunk;
+ int optlen;
+
+ optlen = prepare_dhcp(this, transaction, DHCP_RELEASE, &dhcp);
+
+ release = transaction->get_address(transaction);
+ server = transaction->get_server(transaction);
+ if (!release || !server)
+ {
+ return;
+ }
+ DBG1(DBG_CFG, "sending DHCP RELEASE for %H to %H", release, server);
+
+ chunk = release->get_address(release);
+ memcpy(&dhcp.client_address, chunk.ptr,
+ min(chunk.len, sizeof(dhcp.client_address)));
+
+ option = (dhcp_option_t*)&dhcp.options[optlen];
+ option->type = DHCP_SERVER_ID;
+ option->len = 4;
+ chunk = server->get_address(server);
+ memcpy(option->data, chunk.ptr, min(chunk.len, option->len));
+ optlen += sizeof(dhcp_option_t) + option->len;
+
+ dhcp.options[optlen++] = DHCP_OPTEND;
+
+ if (!send_dhcp(this, transaction, &dhcp, optlen))
+ {
+ DBG1(DBG_CFG, "sending DHCP RELEASE failed: %s", strerror(errno));
+ }
+}
+
+/**
+ * Handle a DHCP OFFER
+ */
+static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen)
+{
+ dhcp_transaction_t *transaction = NULL;
+ enumerator_t *enumerator;
+ host_t *offer, *server;
+
+ offer = host_create_from_chunk(AF_INET,
+ chunk_from_thing(dhcp->your_address), 0);
+ server = host_create_from_chunk(AF_INET,
+ chunk_from_thing(dhcp->server_address), DHCP_SERVER_PORT);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->discover->create_enumerator(this->discover);
+ while (enumerator->enumerate(enumerator, &transaction))
+ {
+ if (transaction->get_id(transaction) == dhcp->transaction_id)
+ {
+ DBG1(DBG_CFG, "received DHCP OFFER %H from %H", offer, server);
+ this->discover->remove_at(this->discover, enumerator);
+ this->request->insert_last(this->request, transaction);
+ transaction->set_address(transaction, offer->clone(offer));
+ transaction->set_server(transaction, server->clone(server));
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (transaction)
+ {
+ int optsize, optpos = 0, pos;
+ dhcp_option_t *option;
+
+ while (optlen > sizeof(dhcp_option_t))
+ {
+ option = (dhcp_option_t*)&dhcp->options[optpos];
+ optsize = sizeof(dhcp_option_t) + option->len;
+ if (option->type == DHCP_OPTEND || optlen < optsize)
+ {
+ break;
+ }
+ if (option->type == DHCP_DNS_SERVER ||
+ option->type == DHCP_NBNS_SERVER)
+ {
+ for (pos = 0; pos + 4 <= option->len; pos += 4)
+ {
+ transaction->add_attribute(transaction, option->type ==
+ DHCP_DNS_SERVER ? INTERNAL_IP4_DNS : INTERNAL_IP4_NBNS,
+ chunk_create((char*)&option->data[pos], 4));
+ }
+ }
+ optlen -= optsize;
+ optpos += optsize;
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ this->condvar->broadcast(this->condvar);
+ offer->destroy(offer);
+ server->destroy(server);
+}
+
+/**
+ * Handle a DHCP ACK
+ */
+static void handle_ack(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen)
+{
+ dhcp_transaction_t *transaction;
+ enumerator_t *enumerator;
+ host_t *offer;
+
+ offer = host_create_from_chunk(AF_INET,
+ chunk_from_thing(dhcp->your_address), 0);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->request->create_enumerator(this->request);
+ while (enumerator->enumerate(enumerator, &transaction))
+ {
+ if (transaction->get_id(transaction) == dhcp->transaction_id)
+ {
+ DBG1(DBG_CFG, "received DHCP ACK for %H", offer);
+ this->request->remove_at(this->request, enumerator);
+ this->completed->insert_last(this->completed, transaction);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+ this->condvar->broadcast(this->condvar);
+ offer->destroy(offer);
+}
+
+/**
+ * Receive DHCP responses
+ */
+static job_requeue_t receive_dhcp(private_dhcp_socket_t *this)
+{
+ struct sockaddr_ll addr;
+ socklen_t addr_len = sizeof(addr);
+ struct __attribute__((packed)) {
+ struct iphdr ip;
+ struct udphdr udp;
+ dhcp_t dhcp;
+ } packet;
+ int oldstate, optlen, origoptlen, optsize, optpos = 0;
+ ssize_t len;
+ dhcp_option_t *option;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->receive, &packet, sizeof(packet), 0,
+ (struct sockaddr*)&addr, &addr_len);
+ thread_cancelability(oldstate);
+
+ if (len >= sizeof(struct iphdr) + sizeof(struct udphdr) +
+ offsetof(dhcp_t, options))
+ {
+ origoptlen = optlen = len - sizeof(struct iphdr) +
+ sizeof(struct udphdr) + offsetof(dhcp_t, options);
+ while (optlen > sizeof(dhcp_option_t))
+ {
+ option = (dhcp_option_t*)&packet.dhcp.options[optpos];
+ optsize = sizeof(dhcp_option_t) + option->len;
+ if (option->type == DHCP_OPTEND || optlen < optsize)
+ {
+ break;
+ }
+ if (option->type == DHCP_MESSAGE_TYPE && option->len == 1)
+ {
+ switch (option->data[0])
+ {
+ case DHCP_OFFER:
+ handle_offer(this, &packet.dhcp, origoptlen);
+ break;
+ case DHCP_ACK:
+ handle_ack(this, &packet.dhcp, origoptlen);
+ default:
+ break;
+ }
+ break;
+ }
+ optlen -= optsize;
+ optpos += optsize;
+ }
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(dhcp_socket_t, destroy, void,
+ private_dhcp_socket_t *this)
+{
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ while (this->waiting)
+ {
+ this->condvar->signal(this->condvar);
+ }
+ if (this->send > 0)
+ {
+ close(this->send);
+ }
+ if (this->receive > 0)
+ {
+ close(this->receive);
+ }
+ this->mutex->destroy(this->mutex);
+ this->condvar->destroy(this->condvar);
+ this->discover->destroy_offset(this->discover,
+ offsetof(dhcp_transaction_t, destroy));
+ this->request->destroy_offset(this->request,
+ offsetof(dhcp_transaction_t, destroy));
+ this->completed->destroy_offset(this->completed,
+ offsetof(dhcp_transaction_t, destroy));
+ DESTROY_IF(this->rng);
+ DESTROY_IF(this->dst);
+ free(this);
+}
+
+/**
+ * See header
+ */
+dhcp_socket_t *dhcp_socket_create()
+{
+ private_dhcp_socket_t *this;
+ struct sockaddr_in src;
+ int on = 1;
+ struct sock_filter dhcp_filter_code[] = {
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS,
+ offsetof(struct iphdr, protocol)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 16),
+ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, sizeof(struct iphdr) +
+ offsetof(struct udphdr, source)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, DHCP_SERVER_PORT, 0, 14),
+ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, sizeof(struct iphdr) +
+ offsetof(struct udphdr, dest)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, DHCP_CLIENT_PORT, 0, 2),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, DHCP_SERVER_PORT, 0, 1),
+ BPF_JUMP(BPF_JMP+BPF_JA, 0, 0, 10),
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, sizeof(struct iphdr) +
+ sizeof(struct udphdr) + offsetof(dhcp_t, opcode)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, BOOTREPLY, 0, 8),
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, sizeof(struct iphdr) +
+ sizeof(struct udphdr) + offsetof(dhcp_t, hw_type)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPHRD_ETHER, 0, 6),
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, sizeof(struct iphdr) +
+ sizeof(struct udphdr) + offsetof(dhcp_t, hw_addr_len)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 4),
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, sizeof(struct iphdr) +
+ sizeof(struct udphdr) + offsetof(dhcp_t, magic_cookie)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x63825363, 0, 2),
+ BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
+ BPF_STMT(BPF_RET+BPF_A, 0),
+ BPF_STMT(BPF_RET+BPF_K, 0),
+ };
+ struct sock_fprog dhcp_filter = {
+ sizeof(dhcp_filter_code) / sizeof(struct sock_filter),
+ dhcp_filter_code,
+ };
+
+ INIT(this,
+ .public = {
+ .enroll = _enroll,
+ .release = _release,
+ .destroy = _destroy,
+ },
+ .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .discover = linked_list_create(),
+ .request = linked_list_create(),
+ .completed = linked_list_create(),
+ );
+
+ if (!this->rng)
+ {
+ DBG1(DBG_CFG, "unable to create RNG");
+ destroy(this);
+ return NULL;
+ }
+ this->identity_lease = lib->settings->get_bool(lib->settings,
+ "charon.plugins.dhcp.identity_lease", FALSE);
+ this->dst = host_create_from_string(lib->settings->get_str(lib->settings,
+ "charon.plugins.dhcp.server", "255.255.255.255"),
+ DHCP_SERVER_PORT);
+ if (!this->dst)
+ {
+ DBG1(DBG_CFG, "configured DHCP server address invalid");
+ destroy(this);
+ return NULL;
+ }
+
+ this->send = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (this->send == -1)
+ {
+ DBG1(DBG_CFG, "unable to create DHCP send socket: %s", strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+ if (setsockopt(this->send, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
+ {
+ DBG1(DBG_CFG, "unable to reuse DHCP socket address: %s", strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+ if (setsockopt(this->send, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1)
+ {
+ DBG1(DBG_CFG, "unable to broadcast on DHCP socket: %s", strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+ src.sin_family = AF_INET;
+ src.sin_port = htons(DHCP_CLIENT_PORT);
+ src.sin_addr.s_addr = INADDR_ANY;
+ if (bind(this->send, (struct sockaddr*)&src, sizeof(src)) == -1)
+ {
+ DBG1(DBG_CFG, "unable to bind DHCP send socket: %s", strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+
+ this->receive = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+ if (this->receive == -1)
+ {
+ DBG1(DBG_NET, "opening DHCP receive socket failed: %s", strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+ if (setsockopt(this->receive, SOL_SOCKET, SO_ATTACH_FILTER,
+ &dhcp_filter, sizeof(dhcp_filter)) < 0)
+ {
+ DBG1(DBG_CFG, "installing DHCP socket filter failed: %s",
+ strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_dhcp,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.h b/src/libcharon/plugins/dhcp/dhcp_socket.h
new file mode 100644
index 000000000..0a8398aba
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup dhcp_socket dhcp_socket
+ * @{ @ingroup dhcp
+ */
+
+#ifndef DHCP_SOCKET_H_
+#define DHCP_SOCKET_H_
+
+typedef struct dhcp_socket_t dhcp_socket_t;
+
+#include "dhcp_transaction.h"
+
+/**
+ * DHCP socket implementation
+ */
+struct dhcp_socket_t {
+
+ /**
+ * Enroll a client address using DHCP.
+ *
+ * @param identity peer identity to enroll an address for
+ * @return completed DHCP transaction, NULL on failure
+ */
+ dhcp_transaction_t* (*enroll)(dhcp_socket_t *this,
+ identification_t *identity);
+
+ /**
+ * Release an enrolled DHCP address.
+ *
+ * @param transaction transaction returned by enroll
+ */
+ void (*release)(dhcp_socket_t *this, dhcp_transaction_t *transaction);
+
+ /**
+ * Destroy a dhcp_socket_t.
+ */
+ void (*destroy)(dhcp_socket_t *this);
+};
+
+/**
+ * Create a dhcp_socket instance.
+ */
+dhcp_socket_t *dhcp_socket_create();
+
+#endif /** DHCP_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/dhcp/dhcp_transaction.c b/src/libcharon/plugins/dhcp/dhcp_transaction.c
new file mode 100644
index 000000000..83f822dd8
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_transaction.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "dhcp_transaction.h"
+
+#include <utils/linked_list.h>
+
+typedef struct private_dhcp_transaction_t private_dhcp_transaction_t;
+
+/**
+ * Private data of an dhcp_transaction_t object.
+ */
+struct private_dhcp_transaction_t {
+
+ /**
+ * Public dhcp_transaction_t interface.
+ */
+ dhcp_transaction_t public;
+
+ /**
+ * DHCP transaction ID
+ */
+ u_int32_t id;
+
+ /**
+ * Peer identity
+ */
+ identification_t *identity;
+
+ /**
+ * received DHCP address
+ */
+ host_t *address;
+
+ /**
+ * discovered DHCP server address
+ */
+ host_t *server;
+
+ /**
+ * List of added attributes, as attribute_entry_t
+ */
+ linked_list_t *attributes;
+};
+
+/**
+ * Entry for an added attribute
+ */
+typedef struct {
+ configuration_attribute_type_t type;
+ chunk_t data;
+} attribute_entry_t;
+
+METHOD(dhcp_transaction_t, get_id, u_int32_t,
+ private_dhcp_transaction_t *this)
+{
+ return this->id;
+}
+
+METHOD(dhcp_transaction_t, get_identity, identification_t*,
+ private_dhcp_transaction_t *this)
+{
+ return this->identity;
+}
+
+METHOD(dhcp_transaction_t, set_address, void,
+ private_dhcp_transaction_t *this, host_t *address)
+{
+ DESTROY_IF(this->address);
+ this->address = address;
+}
+
+METHOD(dhcp_transaction_t, get_address, host_t*,
+ private_dhcp_transaction_t *this)
+{
+ return this->address;
+}
+
+METHOD(dhcp_transaction_t, set_server, void,
+ private_dhcp_transaction_t *this, host_t *server)
+{
+ DESTROY_IF(this->server);
+ this->server = server;
+}
+
+METHOD(dhcp_transaction_t, get_server, host_t*,
+ private_dhcp_transaction_t *this)
+{
+ return this->server;
+}
+
+METHOD(dhcp_transaction_t, add_attribute, void,
+ private_dhcp_transaction_t *this, configuration_attribute_type_t type,
+ chunk_t data)
+{
+ attribute_entry_t *entry;
+
+ INIT(entry,
+ .type = type,
+ .data = chunk_clone(data),
+ );
+ this->attributes->insert_last(this->attributes, entry);
+}
+
+/**
+ * Filter function to map entries to type/data
+ */
+static bool attribute_filter(void *null, attribute_entry_t **entry,
+ configuration_attribute_type_t *type,
+ void **dummy, chunk_t *data)
+{
+ *type = (*entry)->type;
+ *data = (*entry)->data;
+ return TRUE;
+}
+
+METHOD(dhcp_transaction_t, create_attribute_enumerator, enumerator_t*,
+ private_dhcp_transaction_t *this)
+{
+ return enumerator_create_filter(
+ this->attributes->create_enumerator(this->attributes),
+ (void*)attribute_filter, NULL, NULL);
+}
+
+/**
+ * Clean up an attribute entry
+ */
+static void attribute_entry_destroy(attribute_entry_t *entry)
+{
+ free(entry->data.ptr);
+ free(entry);
+}
+
+METHOD(dhcp_transaction_t, destroy, void,
+ private_dhcp_transaction_t *this)
+{
+ this->identity->destroy(this->identity);
+ DESTROY_IF(this->address);
+ DESTROY_IF(this->server);
+ this->attributes->destroy_function(this->attributes,
+ (void*)attribute_entry_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+dhcp_transaction_t *dhcp_transaction_create(u_int32_t id,
+ identification_t *identity)
+{
+ private_dhcp_transaction_t *this;
+
+ INIT(this,
+ .public = {
+ .get_id = _get_id,
+ .get_identity = _get_identity,
+ .set_address = _set_address,
+ .get_address = _get_address,
+ .set_server = _set_server,
+ .get_server = _get_server,
+ .add_attribute = _add_attribute,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ .destroy = _destroy,
+ },
+ .id = id,
+ .identity = identity->clone(identity),
+ .attributes = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/dhcp/dhcp_transaction.h b/src/libcharon/plugins/dhcp/dhcp_transaction.h
new file mode 100644
index 000000000..19c163f88
--- /dev/null
+++ b/src/libcharon/plugins/dhcp/dhcp_transaction.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup dhcp_transaction dhcp_transaction
+ * @{ @ingroup dhcp
+ */
+
+#ifndef DHCP_TRANSACTION_H_
+#define DHCP_TRANSACTION_H_
+
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <attributes/attributes.h>
+
+typedef struct dhcp_transaction_t dhcp_transaction_t;
+
+/**
+ * DHCP transaction class.
+ */
+struct dhcp_transaction_t {
+
+ /**
+ * Get the DCHP transaction ID.
+ *
+ * @return DHCP transaction identifier
+ */
+ u_int32_t (*get_id)(dhcp_transaction_t *this);
+
+ /**
+ * Get the peer identity this transaction is used for.
+ *
+ * @return peer Identity
+ */
+ identification_t* (*get_identity)(dhcp_transaction_t *this);
+
+ /**
+ * Set the DHCP address received using this transaction.
+ *
+ * @param host received DHCP address
+ */
+ void (*set_address)(dhcp_transaction_t *this, host_t *address);
+
+ /**
+ * Get the DHCP address received using this transaction.
+ *
+ * @return received DHCP address
+ */
+ host_t* (*get_address)(dhcp_transaction_t *this);
+
+ /**
+ * Set the DCHP server address discovered.
+ *
+ * @param server DHCP server address
+ */
+ void (*set_server)(dhcp_transaction_t *this, host_t *server);
+
+ /**
+ * Get the DHCP server address.
+ *
+ * @return DHCP server address
+ */
+ host_t* (*get_server)(dhcp_transaction_t *this);
+
+ /**
+ * An an additional attribute to serve to peer.
+ *
+ * @param type type of attribute
+ * @param data attribute data
+ */
+ void (*add_attribute)(dhcp_transaction_t *this,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Create an enumerator over added attributes.
+ *
+ * @return enumerator over (configuration_attribute_t, chunk_t)
+ */
+ enumerator_t* (*create_attribute_enumerator)(dhcp_transaction_t *this);
+
+ /**
+ * Destroy a dhcp_transaction_t.
+ */
+ void (*destroy)(dhcp_transaction_t *this);
+};
+
+/**
+ * Create a dhcp_transaction instance.
+ *
+ * @param id DHCP transaction identifier
+ * @param identity peer identity this transaction is used for
+ * @return transaction instance
+ */
+dhcp_transaction_t *dhcp_transaction_create(u_int32_t id,
+ identification_t *identity);
+
+#endif /** DHCP_TRANSACTION_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka/Makefile.am b/src/libcharon/plugins/eap_aka/Makefile.am
new file mode 100644
index 000000000..d37d1691c
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-aka.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-aka.la
+libstrongswan_eap_aka_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la
+endif
+
+libstrongswan_eap_aka_la_SOURCES = \
+ eap_aka_plugin.h eap_aka_plugin.c \
+ eap_aka_peer.h eap_aka_peer.c \
+ eap_aka_server.h eap_aka_server.c
+
+libstrongswan_eap_aka_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
new file mode 100644
index 000000000..1cea81a9b
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -0,0 +1,593 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_aka
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_eap_aka_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la
+am_libstrongswan_eap_aka_la_OBJECTS = eap_aka_plugin.lo \
+ eap_aka_peer.lo eap_aka_server.lo
+libstrongswan_eap_aka_la_OBJECTS = \
+ $(am_libstrongswan_eap_aka_la_OBJECTS)
+libstrongswan_eap_aka_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_aka_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_aka_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_aka_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_aka_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_aka_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-aka.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-aka.la
+@MONOLITHIC_FALSE@libstrongswan_eap_aka_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la
+libstrongswan_eap_aka_la_SOURCES = \
+ eap_aka_plugin.h eap_aka_plugin.c \
+ eap_aka_peer.h eap_aka_peer.c \
+ eap_aka_server.h eap_aka_server.c
+
+libstrongswan_eap_aka_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_aka/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_aka/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-aka.la: $(libstrongswan_eap_aka_la_OBJECTS) $(libstrongswan_eap_aka_la_DEPENDENCIES)
+ $(libstrongswan_eap_aka_la_LINK) $(am_libstrongswan_eap_aka_la_rpath) $(libstrongswan_eap_aka_la_OBJECTS) $(libstrongswan_eap_aka_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_peer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_server.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
new file mode 100644
index 000000000..26546809d
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2006-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 "eap_aka_peer.h"
+
+#include <library.h>
+#include <daemon.h>
+
+#include <simaka_message.h>
+#include <simaka_crypto.h>
+
+typedef struct private_eap_aka_peer_t private_eap_aka_peer_t;
+
+/**
+ * Private data of an eap_aka_peer_t object.
+ */
+struct private_eap_aka_peer_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_aka_peer_t public;
+
+ /**
+ * EAP-AKA crypto helper
+ */
+ simaka_crypto_t *crypto;
+
+ /**
+ * permanent ID of peer
+ */
+ identification_t *permanent;
+
+ /**
+ * Pseudonym identity the peer uses
+ */
+ identification_t *pseudonym;
+
+ /**
+ * Reauthentication identity the peer uses
+ */
+ identification_t *reauth;
+
+ /**
+ * MSK
+ */
+ chunk_t msk;
+
+ /**
+ * Master key, if reauthentication is used
+ */
+ char mk[HASH_SIZE_SHA1];
+
+ /**
+ * Counter value if reauthentication is used
+ */
+ u_int16_t counter;
+};
+
+/**
+ * Create a AKA_CLIENT_ERROR: "Unable to process"
+ */
+static eap_payload_t* create_client_error(private_eap_aka_peer_t *this,
+ u_int8_t identifier)
+{
+ simaka_message_t *message;
+ eap_payload_t *out;
+ u_int16_t encoded;
+
+ DBG1(DBG_IKE, "sending client error '%N'",
+ simaka_client_error_names, AKA_UNABLE_TO_PROCESS);
+
+ message = simaka_message_create(FALSE, identifier, EAP_AKA,
+ AKA_CLIENT_ERROR, this->crypto);
+ encoded = htons(AKA_UNABLE_TO_PROCESS);
+ message->add_attribute(message, AT_CLIENT_ERROR_CODE,
+ chunk_create((char*)&encoded, sizeof(encoded)));
+ out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ return out;
+}
+
+/**
+ * process an EAP-AKA/Request/Identity message
+ */
+static status_t process_identity(private_eap_aka_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, id = chunk_empty;
+ simaka_attribute_t id_req = 0;
+
+ /* reset previously uses reauthentication/pseudonym data */
+ this->crypto->clear_keys(this->crypto);
+ DESTROY_IF(this->pseudonym);
+ this->pseudonym = NULL;
+ DESTROY_IF(this->reauth);
+ this->reauth = NULL;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_ANY_ID_REQ:
+ case AT_FULLAUTH_ID_REQ:
+ case AT_PERMANENT_ID_REQ:
+ id_req = type;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ switch (id_req)
+ {
+ case AT_ANY_ID_REQ:
+ this->reauth = charon->sim->card_get_reauth(charon->sim,
+ this->permanent, this->mk, &this->counter);
+ if (this->reauth)
+ {
+ id = this->reauth->get_encoding(this->reauth);
+ break;
+ }
+ /* FALL */
+ case AT_FULLAUTH_ID_REQ:
+ this->pseudonym = charon->sim->card_get_pseudonym(charon->sim,
+ this->permanent);
+ if (this->pseudonym)
+ {
+ id = this->pseudonym->get_encoding(this->pseudonym);
+ break;
+ }
+ /* FALL */
+ case AT_PERMANENT_ID_REQ:
+ id = this->permanent->get_encoding(this->permanent);
+ break;
+ default:
+ break;
+ }
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_IDENTITY, this->crypto);
+ if (id.len)
+ {
+ message->add_attribute(message, AT_IDENTITY, id);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Process an EAP-AKA/Request/Challenge message
+ */
+static status_t process_challenge(private_eap_aka_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, rand = chunk_empty, autn = chunk_empty, mk;
+ u_char res[AKA_RES_MAX], ck[AKA_CK_LEN], ik[AKA_IK_LEN], auts[AKA_AUTS_LEN];
+ int res_len;
+ identification_t *id;
+ status_t status;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_RAND:
+ rand = data;
+ break;
+ case AT_AUTN:
+ autn = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!rand.len || !autn.len)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-AKA challenge message");
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+
+ status = charon->sim->card_get_quintuplet(charon->sim, this->permanent,
+ rand.ptr, autn.ptr, ck, ik, res, &res_len);
+ if (status == INVALID_STATE &&
+ charon->sim->card_resync(charon->sim, this->permanent, rand.ptr, auts))
+ {
+ DBG1(DBG_IKE, "received SQN invalid, sending %N",
+ simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_SYNCHRONIZATION_FAILURE, this->crypto);
+ message->add_attribute(message, AT_AUTS,
+ chunk_create(auts, AKA_AUTS_LEN));
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ return NEED_MORE;
+ }
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "no USIM found with quintuplets for '%Y', sending %N",
+ this->permanent, simaka_subtype_names, AKA_AUTHENTICATION_REJECT);
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_AUTHENTICATION_REJECT, this->crypto);
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ return NEED_MORE;
+ }
+
+ id = this->permanent;
+ if (this->pseudonym)
+ {
+ id = this->pseudonym;
+ }
+ data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
+ chunk_create(ck, AKA_CK_LEN));
+ free(this->msk.ptr);
+ this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ memcpy(this->mk, mk.ptr, mk.len);
+ free(mk.ptr);
+
+ /* Verify AT_MAC attribute and parse() again after key derivation,
+ * reading encrypted attributes */
+ if (!in->verify(in, chunk_empty) || !in->parse(in))
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_NEXT_REAUTH_ID:
+ this->counter = 0;
+ id = identification_create_from_data(data);
+ charon->sim->card_set_reauth(charon->sim, this->permanent, id,
+ this->mk, this->counter);
+ id->destroy(id);
+ break;
+ case AT_NEXT_PSEUDONYM:
+ id = identification_create_from_data(data);
+ charon->sim->card_set_pseudonym(charon->sim, this->permanent, id);
+ id->destroy(id);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_CHALLENGE, this->crypto);
+ message->add_attribute(message, AT_RES, chunk_create(res, res_len));
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ return NEED_MORE;
+}
+
+/**
+ * Check if a received counter value is acceptable
+ */
+static bool counter_too_small(private_eap_aka_peer_t *this, chunk_t chunk)
+{
+ u_int16_t counter;
+
+ memcpy(&counter, chunk.ptr, sizeof(counter));
+ counter = htons(counter);
+ return counter < this->counter;
+}
+
+/**
+ * process an EAP-AKA/Request/Reauthentication message
+ */
+static status_t process_reauthentication(private_eap_aka_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, counter = chunk_empty, nonce = chunk_empty, id = chunk_empty;
+
+ if (!this->reauth)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, AKA_REAUTHENTICATION);
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+
+ this->crypto->derive_keys_reauth(this->crypto,
+ chunk_create(this->mk, HASH_SIZE_SHA1));
+
+ /* verify MAC and parse again with decryption key */
+ if (!in->verify(in, chunk_empty) || !in->parse(in))
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_COUNTER:
+ counter = data;
+ break;
+ case AT_NONCE_S:
+ nonce = data;
+ break;
+ case AT_NEXT_REAUTH_ID:
+ id = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!nonce.len || !counter.len)
+ {
+ DBG1(DBG_IKE, "EAP-AKA/Request/Reauthentication message incomplete");
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_REAUTHENTICATION, this->crypto);
+ if (counter_too_small(this, counter))
+ {
+ DBG1(DBG_IKE, "reauthentication counter too small");
+ message->add_attribute(message, AT_COUNTER_TOO_SMALL, chunk_empty);
+ }
+ else
+ {
+ free(this->msk.ptr);
+ this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, counter, nonce,
+ chunk_create(this->mk, HASH_SIZE_SHA1));
+ if (id.len)
+ {
+ identification_t *reauth;
+
+ reauth = identification_create_from_data(data);
+ charon->sim->card_set_reauth(charon->sim, this->permanent, reauth,
+ this->mk, this->counter);
+ reauth->destroy(reauth);
+ }
+ }
+ message->add_attribute(message, AT_COUNTER, counter);
+ *out = message->generate(message, nonce);
+ message->destroy(message);
+ return NEED_MORE;
+}
+
+/**
+ * Process an EAP-AKA/Request/Notification message
+ */
+static status_t process_notification(private_eap_aka_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data;
+ bool success = TRUE;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == AT_NOTIFICATION)
+ {
+ u_int16_t code;
+
+ memcpy(&code, data.ptr, sizeof(code));
+ code = ntohs(code);
+
+ /* test success bit */
+ if (!(data.ptr[0] & 0x80))
+ {
+ success = FALSE;
+ DBG1(DBG_IKE, "received EAP-AKA notification error '%N'",
+ simaka_notification_names, code);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received EAP-AKA notification '%N'",
+ simaka_notification_names, code);
+ }
+ }
+ else if (!simaka_attribute_skippable(type))
+ {
+ success = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (success)
+ { /* empty notification reply */
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
+ AKA_NOTIFICATION, this->crypto);
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ }
+ else
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ }
+ return NEED_MORE;
+}
+
+
+/**
+ * Implementation of eap_method_t.process
+ */
+static status_t process(private_eap_aka_peer_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ status_t status;
+
+ message = simaka_message_create_from_payload(in, this->crypto);
+ if (!message)
+ {
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+ if (!message->parse(message))
+ {
+ message->destroy(message);
+ *out = create_client_error(this, in->get_identifier(in));
+ return NEED_MORE;
+ }
+ switch (message->get_subtype(message))
+ {
+ case AKA_IDENTITY:
+ status = process_identity(this, message, out);
+ break;
+ case AKA_CHALLENGE:
+ status = process_challenge(this, message, out);
+ break;
+ case AKA_REAUTHENTICATION:
+ status = process_reauthentication(this, message, out);
+ break;
+ case AKA_NOTIFICATION:
+ status = process_notification(this, message, out);
+ break;
+ default:
+ DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N",
+ simaka_subtype_names, message->get_subtype(message));
+ *out = create_client_error(this, in->get_identifier(in));
+ status = NEED_MORE;
+ break;
+ }
+ message->destroy(message);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.initiate
+ */
+static status_t initiate(private_eap_aka_peer_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_aka_peer_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_AKA;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_aka_peer_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_aka_peer_t *this)
+{
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_aka_peer_t *this)
+{
+ this->crypto->destroy(this->crypto);
+ this->permanent->destroy(this->permanent);
+ DESTROY_IF(this->pseudonym);
+ DESTROY_IF(this->reauth);
+ free(this->msk.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+eap_aka_peer_t *eap_aka_peer_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_aka_peer_t *this = malloc_thing(private_eap_aka_peer_t);
+
+ this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
+ this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->crypto = simaka_crypto_create();
+ if (!this->crypto)
+ {
+ free(this);
+ return NULL;
+ }
+ this->permanent = peer->clone(peer);
+ this->pseudonym = NULL;
+ this->reauth = NULL;
+ this->msk = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.h b/src/libcharon/plugins/eap_aka/eap_aka_peer.h
new file mode 100644
index 000000000..65a210406
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_peer eap_aka_peer
+ * @{ @ingroup eap_aka
+ */
+
+#ifndef EAP_AKA_PEER_H_
+#define EAP_AKA_PEER_H_
+
+typedef struct eap_aka_peer_t eap_aka_peer_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP-AKA as a client.
+ */
+struct eap_aka_peer_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t interface;
+};
+
+/**
+ * Creates the peer implementation of the EAP method EAP-AKA.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_aka_peer_t object
+ */
+eap_aka_peer_t *eap_aka_peer_create(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_AKA_PEER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_plugin.c b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c
new file mode 100644
index 000000000..f9283393a
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008-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 "eap_aka_plugin.h"
+
+#include "eap_aka_peer.h"
+#include "eap_aka_server.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_aka_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_aka_server_create);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_aka_peer_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_aka_plugin_create()
+{
+ eap_aka_plugin_t *this = malloc_thing(eap_aka_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_SERVER,
+ (eap_constructor_t)eap_aka_server_create);
+ charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_PEER,
+ (eap_constructor_t)eap_aka_peer_create);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_plugin.h b/src/libcharon/plugins/eap_aka/eap_aka_plugin.h
new file mode 100644
index 000000000..d011904b3
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_plugin.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008-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 eap_aka eap_aka
+ * @ingroup cplugins
+ *
+ * @defgroup eap_aka_plugin eap_aka_plugin
+ * @{ @ingroup eap_aka
+ */
+
+#ifndef EAP_AKA_PLUGIN_H_
+#define EAP_AKA_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_aka_plugin_t eap_aka_plugin_t;
+
+/**
+ * EAP-AKA plugin.
+ *
+ * EAP-AKA uses 3rd generation mobile phone standard authentication
+ * mechanism for authentication, as defined RFC4187.
+ */
+struct eap_aka_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_AKA_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c
new file mode 100644
index 000000000..9baff3e23
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2006-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 "eap_aka_server.h"
+
+#include <daemon.h>
+#include <library.h>
+
+#include <simaka_message.h>
+#include <simaka_crypto.h>
+
+/** length of the AT_NONCE_S value */
+#define NONCE_LEN 16
+
+typedef struct private_eap_aka_server_t private_eap_aka_server_t;
+
+/**
+ * Private data of an eap_aka_server_t object.
+ */
+struct private_eap_aka_server_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_aka_server_t public;
+
+ /**
+ * EAP-AKA crypto helper
+ */
+ simaka_crypto_t *crypto;
+
+ /**
+ * permanent ID of the peer
+ */
+ identification_t *permanent;
+
+ /**
+ * pseudonym ID of peer
+ */
+ identification_t *pseudonym;
+
+ /**
+ * reauthentication ID of peer
+ */
+ identification_t *reauth;
+
+ /**
+ * EAP identifier value
+ */
+ u_int8_t identifier;
+
+ /**
+ * Expected Result XRES
+ */
+ chunk_t xres;
+
+ /**
+ * Random value RAND
+ */
+ chunk_t rand;
+
+ /**
+ * MSK
+ */
+ chunk_t msk;
+
+ /**
+ * Nonce value used in AT_NONCE_S
+ */
+ chunk_t nonce;
+
+ /**
+ * Counter value negotiated, network order
+ */
+ chunk_t counter;
+
+ /**
+ * Do we request fast reauthentication?
+ */
+ bool use_reauth;
+
+ /**
+ * Do we request pseudonym identities?
+ */
+ bool use_pseudonym;
+
+ /**
+ * Do we request permanent identities?
+ */
+ bool use_permanent;
+
+ /**
+ * EAP-AKA message we have initiated
+ */
+ simaka_subtype_t pending;
+
+ /**
+ * Did the client send a synchronize request?
+ */
+ bool synchronized;
+};
+
+/**
+ * Create EAP-AKA/Request/Identity message
+ */
+static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out)
+{
+ simaka_message_t *message;
+
+ message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
+ AKA_IDENTITY, this->crypto);
+ if (this->use_reauth)
+ {
+ message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty);
+ }
+ else if (this->use_pseudonym)
+ {
+ message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty);
+ }
+ else if (this->use_permanent)
+ {
+ message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ this->pending = AKA_IDENTITY;
+ return NEED_MORE;
+}
+
+/**
+ * Create EAP-AKA/Request/Challenge message
+ */
+static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ char rand[AKA_RAND_LEN], xres[AKA_RES_MAX];
+ char ck[AKA_CK_LEN], ik[AKA_IK_LEN], autn[AKA_AUTN_LEN];
+ int xres_len;
+ chunk_t data, mk;
+ identification_t *id;
+
+ if (!charon->sim->provider_get_quintuplet(charon->sim, this->permanent,
+ rand, xres, &xres_len, ck, ik, autn))
+ {
+ if (this->use_pseudonym)
+ {
+ /* probably received a pseudonym/reauth id we couldn't map */
+ DBG1(DBG_IKE, "failed to map pseudonym/reauth identity '%Y', "
+ "fallback to permanent identity request", this->permanent);
+ this->use_pseudonym = FALSE;
+ DESTROY_IF(this->pseudonym);
+ this->pseudonym = NULL;
+ return identity(this, out);
+ }
+ return FAILED;
+ }
+ id = this->permanent;
+ if (this->pseudonym)
+ {
+ id = this->pseudonym;
+ }
+ data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
+ chunk_create(ck, AKA_CK_LEN));
+ free(this->msk.ptr);
+ this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ this->rand = chunk_clone(chunk_create(rand, AKA_RAND_LEN));
+ this->xres = chunk_clone(chunk_create(xres, xres_len));
+
+ message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
+ AKA_CHALLENGE, this->crypto);
+ message->add_attribute(message, AT_RAND, this->rand);
+ message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN));
+ id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr);
+ if (id)
+ {
+ message->add_attribute(message, AT_NEXT_REAUTH_ID,
+ id->get_encoding(id));
+ id->destroy(id);
+ }
+ else
+ {
+ id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent);
+ if (id)
+ {
+ message->add_attribute(message, AT_NEXT_PSEUDONYM,
+ id->get_encoding(id));
+ id->destroy(id);
+ }
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ free(mk.ptr);
+ this->pending = AKA_CHALLENGE;
+ return NEED_MORE;
+}
+
+/**
+ * Initiate EAP-AKA/Request/Re-authentication message
+ */
+static status_t reauthenticate(private_eap_aka_server_t *this,
+ char mk[HASH_SIZE_SHA1], u_int16_t counter,
+ eap_payload_t **out)
+{
+ simaka_message_t *message;
+ identification_t *next;
+ chunk_t mkc;
+ rng_t *rng;
+
+ DBG1(DBG_IKE, "initiating EAP-AKA reauthentication");
+
+ rng = this->crypto->get_rng(this->crypto);
+ rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+
+ mkc = chunk_create(mk, HASH_SIZE_SHA1);
+ counter = htons(counter);
+ this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
+
+ this->crypto->derive_keys_reauth(this->crypto, mkc);
+ this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, this->counter, this->nonce, mkc);
+
+ message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
+ AKA_REAUTHENTICATION, this->crypto);
+ message->add_attribute(message, AT_COUNTER, this->counter);
+ message->add_attribute(message, AT_NONCE_S, this->nonce);
+ next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk);
+ if (next)
+ {
+ message->add_attribute(message, AT_NEXT_REAUTH_ID,
+ next->get_encoding(next));
+ next->destroy(next);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ this->pending = SIM_REAUTHENTICATION;
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.initiate
+ */
+static status_t initiate(private_eap_aka_server_t *this, eap_payload_t **out)
+{
+ if (this->use_permanent || this->use_pseudonym || this->use_reauth)
+ {
+ return identity(this, out);
+ }
+ return challenge(this, out);
+}
+
+/**
+ * Process EAP-AKA/Response/Identity message
+ */
+static status_t process_identity(private_eap_aka_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ identification_t *permanent, *id;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, identity = chunk_empty;
+
+ if (this->pending != AKA_IDENTITY)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, AKA_IDENTITY);
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_IDENTITY:
+ identity = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!identity.len)
+ {
+ DBG1(DBG_IKE, "received incomplete Identity response");
+ return FAILED;
+ }
+
+ id = identification_create_from_data(identity);
+ if (this->use_reauth)
+ {
+ char mk[HASH_SIZE_SHA1];
+ u_int16_t counter;
+
+ permanent = charon->sim->provider_is_reauth(charon->sim, id,
+ mk, &counter);
+ if (permanent)
+ {
+ this->permanent->destroy(this->permanent);
+ this->permanent = permanent;
+ this->reauth = id;
+ return reauthenticate(this, mk, counter, out);
+ }
+ /* unable to map, maybe a pseudonym? */
+ DBG1(DBG_IKE, "'%Y' is not a reauth identity", id);
+ this->use_reauth = FALSE;
+ }
+ if (this->use_pseudonym)
+ {
+ permanent = charon->sim->provider_is_pseudonym(charon->sim, id);
+ if (permanent)
+ {
+ this->permanent->destroy(this->permanent);
+ this->permanent = permanent;
+ this->pseudonym = id->clone(id);
+ /* we already have a new permanent identity now */
+ this->use_permanent = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "'%Y' is not a pseudonym", id);
+ }
+ }
+ if (!this->pseudonym && this->use_permanent)
+ {
+ /* got a permanent identity or a pseudonym reauth id wou couldn't map,
+ * try to get quintuplets */
+ DBG1(DBG_IKE, "received identity '%Y'", id);
+ this->permanent->destroy(this->permanent);
+ this->permanent = id->clone(id);
+ }
+ id->destroy(id);
+
+ return challenge(this, out);
+}
+
+/**
+ * Process EAP-AKA/Response/Challenge message
+ */
+static status_t process_challenge(private_eap_aka_server_t *this,
+ simaka_message_t *in)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, res = chunk_empty;
+
+ if (this->pending != AKA_CHALLENGE)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, AKA_CHALLENGE);
+ return FAILED;
+ }
+ /* verify MAC of EAP message, AT_MAC */
+ if (!in->verify(in, chunk_empty))
+ {
+ return FAILED;
+ }
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_RES:
+ res = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* compare received RES against stored XRES */
+ if (!chunk_equals(res, this->xres))
+ {
+ DBG1(DBG_IKE, "received RES does not match XRES");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * process an EAP-AKA/Response/Reauthentication message
+ */
+static status_t process_reauthentication(private_eap_aka_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, counter = chunk_empty;
+ bool too_small = FALSE;
+
+ if (this->pending != AKA_REAUTHENTICATION)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, AKA_REAUTHENTICATION);
+ return FAILED;
+ }
+ /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_S" */
+ if (!in->verify(in, this->nonce))
+ {
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_COUNTER:
+ counter = data;
+ break;
+ case AT_COUNTER_TOO_SMALL:
+ too_small = TRUE;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (too_small)
+ {
+ DBG1(DBG_IKE, "received %N, initiating full authentication",
+ simaka_attribute_names, AT_COUNTER_TOO_SMALL);
+ this->use_reauth = FALSE;
+ this->crypto->clear_keys(this->crypto);
+ return challenge(this, out);
+ }
+ if (!chunk_equals(counter, this->counter))
+ {
+ DBG1(DBG_IKE, "received counter does not match");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Process EAP-AKA/Response/SynchronizationFailure message
+ */
+static status_t process_synchronize(private_eap_aka_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, auts = chunk_empty;
+
+ if (this->synchronized)
+ {
+ DBG1(DBG_IKE, "received %N, but peer did already resynchronize",
+ simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
+ return FAILED;
+ }
+
+ DBG1(DBG_IKE, "received synchronization request, retrying...");
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_AUTS:
+ auts = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!auts.len)
+ {
+ DBG1(DBG_IKE, "synchronization request didn't contain usable AUTS");
+ return FAILED;
+ }
+
+ if (!charon->sim->provider_resync(charon->sim, this->permanent,
+ this->rand.ptr, auts.ptr))
+ {
+ DBG1(DBG_IKE, "no AKA provider found supporting "
+ "resynchronization for '%Y'", this->permanent);
+ return FAILED;
+ }
+ this->synchronized = TRUE;
+ return challenge(this, out);
+}
+
+/**
+ * Process EAP-AKA/Response/ClientErrorCode message
+ */
+static status_t process_client_error(private_eap_aka_server_t *this,
+ simaka_message_t *in)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == AT_CLIENT_ERROR_CODE)
+ {
+ u_int16_t code;
+
+ memcpy(&code, data.ptr, sizeof(code));
+ DBG1(DBG_IKE, "received EAP-AKA client error '%N'",
+ simaka_client_error_names, ntohs(code));
+ }
+ else if (!simaka_attribute_skippable(type))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FAILED;
+}
+
+/**
+ * Process EAP-AKA/Response/AuthenticationReject message
+ */
+static status_t process_authentication_reject(private_eap_aka_server_t *this,
+ simaka_message_t *in)
+{
+ DBG1(DBG_IKE, "received %N, authentication failed",
+ simaka_subtype_names, in->get_subtype(in));
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.process
+ */
+static status_t process(private_eap_aka_server_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ status_t status;
+
+ message = simaka_message_create_from_payload(in, this->crypto);
+ if (!message)
+ {
+ return FAILED;
+ }
+ if (!message->parse(message))
+ {
+ message->destroy(message);
+ return FAILED;
+ }
+ switch (message->get_subtype(message))
+ {
+ case AKA_IDENTITY:
+ status = process_identity(this, message, out);
+ break;
+ case AKA_CHALLENGE:
+ status = process_challenge(this, message);
+ break;
+ case AKA_REAUTHENTICATION:
+ status = process_reauthentication(this, message, out);
+ break;
+ case AKA_SYNCHRONIZATION_FAILURE:
+ status = process_synchronize(this, message, out);
+ break;
+ case AKA_CLIENT_ERROR:
+ status = process_client_error(this, message);
+ break;
+ case AKA_AUTHENTICATION_REJECT:
+ status = process_authentication_reject(this, message);
+ break;
+ default:
+ DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N",
+ simaka_subtype_names, message->get_subtype(message));
+ status = FAILED;
+ break;
+ }
+ message->destroy(message);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_aka_server_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_AKA;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_aka_server_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_aka_server_t *this)
+{
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_aka_server_t *this)
+{
+ this->crypto->destroy(this->crypto);
+ this->permanent->destroy(this->permanent);
+ DESTROY_IF(this->pseudonym);
+ DESTROY_IF(this->reauth);
+ free(this->xres.ptr);
+ free(this->rand.ptr);
+ free(this->nonce.ptr);
+ free(this->msk.ptr);
+ free(this->counter.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+eap_aka_server_t *eap_aka_server_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_aka_server_t *this = malloc_thing(private_eap_aka_server_t);
+
+ this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
+ this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->crypto = simaka_crypto_create();
+ if (!this->crypto)
+ {
+ free(this);
+ return NULL;
+ }
+ this->permanent = peer->clone(peer);
+ this->pseudonym = NULL;
+ this->reauth = NULL;
+ this->xres = chunk_empty;
+ this->rand = chunk_empty;
+ this->nonce = chunk_empty;
+ this->msk = chunk_empty;
+ this->counter = chunk_empty;
+ this->pending = 0;
+ this->synchronized = FALSE;
+ this->use_reauth = this->use_pseudonym = this->use_permanent =
+ lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-aka.request_identity", TRUE);
+ /* generate a non-zero identifier */
+ do {
+ this->identifier = random();
+ } while (!this->identifier);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.h b/src/libcharon/plugins/eap_aka/eap_aka_server.h
new file mode 100644
index 000000000..d48fc4c34
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_server eap_aka_server
+ * @{ @ingroup eap_aka
+ */
+
+#ifndef EAP_AKA_SERVER_H_
+#define EAP_AKA_SERVER_H_
+
+typedef struct eap_aka_server_t eap_aka_server_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP-AKA as server.
+ */
+struct eap_aka_server_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t interface;
+};
+
+/**
+ * Creates the server implementation of the EAP method EAP-AKA.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_aka_server_t object
+ */
+eap_aka_server_t *eap_aka_server_create(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_AKA_SERVER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
new file mode 100644
index 000000000..598799e2a
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
@@ -0,0 +1,20 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la
+endif
+
+libstrongswan_eap_aka_3gpp2_la_SOURCES = \
+ eap_aka_3gpp2_plugin.h eap_aka_3gpp2_plugin.c \
+ eap_aka_3gpp2_card.h eap_aka_3gpp2_card.c \
+ eap_aka_3gpp2_provider.h eap_aka_3gpp2_provider.c \
+ eap_aka_3gpp2_functions.h eap_aka_3gpp2_functions.c
+
+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
new file mode 100644
index 000000000..d0b0f5601
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -0,0 +1,596 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_aka_3gpp2
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_aka_3gpp2_la_DEPENDENCIES =
+am_libstrongswan_eap_aka_3gpp2_la_OBJECTS = eap_aka_3gpp2_plugin.lo \
+ eap_aka_3gpp2_card.lo eap_aka_3gpp2_provider.lo \
+ eap_aka_3gpp2_functions.lo
+libstrongswan_eap_aka_3gpp2_la_OBJECTS = \
+ $(am_libstrongswan_eap_aka_3gpp2_la_OBJECTS)
+libstrongswan_eap_aka_3gpp2_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_aka_3gpp2_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_aka_3gpp2_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_aka_3gpp2_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_aka_3gpp2_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_aka_3gpp2_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la
+libstrongswan_eap_aka_3gpp2_la_SOURCES = \
+ eap_aka_3gpp2_plugin.h eap_aka_3gpp2_plugin.c \
+ eap_aka_3gpp2_card.h eap_aka_3gpp2_card.c \
+ eap_aka_3gpp2_provider.h eap_aka_3gpp2_provider.c \
+ eap_aka_3gpp2_functions.h eap_aka_3gpp2_functions.c
+
+libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version
+libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp
+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/eap_aka_3gpp2/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_aka_3gpp2/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-aka-3gpp2.la: $(libstrongswan_eap_aka_3gpp2_la_OBJECTS) $(libstrongswan_eap_aka_3gpp2_la_DEPENDENCIES)
+ $(libstrongswan_eap_aka_3gpp2_la_LINK) $(am_libstrongswan_eap_aka_3gpp2_la_rpath) $(libstrongswan_eap_aka_3gpp2_la_OBJECTS) $(libstrongswan_eap_aka_3gpp2_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_3gpp2_card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_3gpp2_functions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_3gpp2_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_3gpp2_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
new file mode 100644
index 000000000..5c0fe38ad
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2008-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 "eap_aka_3gpp2_card.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_aka_3gpp2_card_t private_eap_aka_3gpp2_card_t;
+
+/**
+ * Private data of an eap_aka_3gpp2_card_t object.
+ */
+struct private_eap_aka_3gpp2_card_t {
+
+ /**
+ * Public eap_aka_3gpp2_card_t interface.
+ */
+ eap_aka_3gpp2_card_t public;
+
+ /**
+ * AKA functions
+ */
+ eap_aka_3gpp2_functions_t *f;
+
+ /**
+ * do sequence number checking?
+ */
+ bool seq_check;
+
+ /**
+ * SQN stored in this pseudo-USIM
+ */
+ char sqn[AKA_SQN_LEN];
+};
+
+/**
+ * Functions from eap_aka_3gpp2_provider.c
+ */
+bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN]);
+void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset);
+
+/**
+ * Implementation of sim_card_t.get_quintuplet
+ */
+static status_t get_quintuplet(private_eap_aka_3gpp2_card_t *this,
+ identification_t *id, char rand[AKA_RAND_LEN],
+ char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
+ char ik[AKA_IK_LEN], char res[AKA_RES_MAX],
+ int *res_len)
+{
+ char *amf, *mac;
+ char k[AKA_K_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN], xmac[AKA_MAC_LEN];
+
+ if (!eap_aka_3gpp2_get_k(id, k))
+ {
+ DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
+ return FAILED;
+ }
+
+ /* AUTN = SQN xor AK | AMF | MAC */
+ DBG3(DBG_IKE, "received autn %b", autn, AKA_AUTN_LEN);
+ DBG3(DBG_IKE, "using K %b", k, AKA_K_LEN);
+ DBG3(DBG_IKE, "using rand %b", rand, AKA_RAND_LEN);
+ memcpy(sqn, autn, AKA_SQN_LEN);
+ amf = autn + AKA_SQN_LEN;
+ mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
+
+ /* XOR anonymity key AK into SQN to decrypt it */
+ this->f->f5(this->f, k, rand, ak);
+ DBG3(DBG_IKE, "using ak %b", ak, AKA_AK_LEN);
+ memxor(sqn, ak, AKA_SQN_LEN);
+ DBG3(DBG_IKE, "using sqn %b", sqn, AKA_SQN_LEN);
+
+ /* calculate expected MAC and compare against received one */
+ this->f->f1(this->f, k, rand, sqn, amf, xmac);
+ if (!memeq(mac, xmac, AKA_MAC_LEN))
+ {
+ DBG1(DBG_IKE, "received MAC does not match XMAC");
+ DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
+ return FAILED;
+ }
+
+ if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0)
+ {
+ DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b",
+ sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN);
+ return INVALID_STATE;
+ }
+
+ /* update stored SQN to the received one */
+ memcpy(this->sqn, sqn, AKA_SQN_LEN);
+
+ /* CK/IK */
+ this->f->f3(this->f, k, rand, ck);
+ this->f->f4(this->f, k, rand, ik);
+ /* calculate RES */
+ this->f->f2(this->f, k, rand, res);
+ *res_len = AKA_RES_MAX;
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of sim_card_t.resync
+ */
+static bool resync(private_eap_aka_3gpp2_card_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
+{
+ char amf[AKA_AMF_LEN], k[AKA_K_LEN], aks[AKA_AK_LEN], macs[AKA_MAC_LEN];
+
+ if (!eap_aka_3gpp2_get_k(id, k))
+ {
+ DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id);
+ return FALSE;
+ }
+
+ /* AMF is set to zero in resync */
+ memset(amf, 0, AKA_AMF_LEN);
+ this->f->f5star(this->f, k, rand, aks);
+ this->f->f1star(this->f, k, rand, this->sqn, amf, macs);
+ /* AUTS = SQN xor AKS | MACS */
+ memcpy(auts, this->sqn, AKA_SQN_LEN);
+ memxor(auts, aks, AKA_AK_LEN);
+ memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_aka_3gpp2_card_t.destroy.
+ */
+static void destroy(private_eap_aka_3gpp2_card_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
+{
+ private_eap_aka_3gpp2_card_t *this = malloc_thing(private_eap_aka_3gpp2_card_t);
+
+ this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false;
+ this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet;
+ this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))resync;
+ this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *id))return_null;
+ this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop;
+ this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop;
+ this->public.destroy = (void(*)(eap_aka_3gpp2_card_t*))destroy;
+
+ this->f = f;
+ this->seq_check = lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-aka-3gpp2.seq_check",
+#ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
+ TRUE);
+#else /* !SEQ_CHECK */
+ FALSE);
+#endif /* SEQ_CHECK */
+
+ eap_aka_3gpp2_get_sqn(this->sqn, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h
new file mode 100644
index 000000000..b95bc52af
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_3gpp2_card eap_aka_3gpp2_card
+ * @{ @ingroup eap_aka_3gpp2
+ */
+
+#ifndef EAP_AKA_3GPP2_CARD_H_
+#define EAP_AKA_3GPP2_CARD_H_
+
+#include "eap_aka_3gpp2_functions.h"
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_aka_3gpp2_card_t eap_aka_3gpp2_card_t;
+
+/**
+ * SIM card implementation using a set of AKA functions.
+ */
+struct eap_aka_3gpp2_card_t {
+
+ /**
+ * Implements sim_card_t interface
+ */
+ sim_card_t card;
+
+ /**
+ * Destroy a eap_aka_3gpp2_card_t.
+ */
+ void (*destroy)(eap_aka_3gpp2_card_t *this);
+};
+
+/**
+ * Create a eap_aka_3gpp2_card instance.
+ *
+ * @param f AKA functions
+ */
+eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f);
+
+#endif /** EAP_AKA_3GPP2_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c
new file mode 100644
index 000000000..1d3d246d1
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2008-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 "eap_aka_3gpp2_functions.h"
+
+#include <gmp.h>
+#include <limits.h>
+
+#include <daemon.h>
+
+typedef struct private_eap_aka_3gpp2_functions_t private_eap_aka_3gpp2_functions_t;
+
+/**
+ * Private data of an eap_aka_3gpp2_functions_t object.
+ */
+struct private_eap_aka_3gpp2_functions_t {
+
+ /**
+ * Public eap_aka_3gpp2_functions_t interface.
+ */
+ eap_aka_3gpp2_functions_t public;
+
+ /**
+ * Used keyed SHA1 function, as PRF
+ */
+ prf_t *prf;
+};
+
+#define AKA_PAYLOAD_LEN 64
+
+#define F1 0x42
+#define F1STAR 0x43
+#define F2 0x44
+#define F3 0x45
+#define F4 0x46
+#define F5 0x47
+#define F5STAR 0x48
+
+/** Family key, as proposed in S.S0055 */
+static chunk_t fmk = chunk_from_chars(0x41, 0x48, 0x41, 0x47);
+
+/**
+ * Binary represnation of the polynom T^160 + T^5 + T^3 + T^2 + 1
+ */
+static u_int8_t g[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2d
+};
+
+/**
+ * Predefined random bits from the RAND Corporation book
+ */
+static u_int8_t a[] = {
+ 0x9d, 0xe9, 0xc9, 0xc8, 0xef, 0xd5, 0x78, 0x11,
+ 0x48, 0x23, 0x14, 0x01, 0x90, 0x1f, 0x2d, 0x49,
+ 0x3f, 0x4c, 0x63, 0x65
+};
+
+/**
+ * Predefined random bits from the RAND Corporation book
+ */
+static u_int8_t b[] = {
+ 0x75, 0xef, 0xd1, 0x5c, 0x4b, 0x8f, 0x8f, 0x51,
+ 0x4e, 0xf3, 0xbc, 0xc3, 0x79, 0x4a, 0x76, 0x5e,
+ 0x7e, 0xec, 0x45, 0xe0
+};
+
+/**
+ * Multiplicate two mpz_t with bits interpreted as polynoms.
+ */
+static void mpz_mul_poly(mpz_t r, mpz_t a, mpz_t b)
+{
+ mpz_t bm, rm;
+ int current = 0, shifted = 0, shift;
+
+ mpz_init_set(bm, b);
+ mpz_init_set_ui(rm, 0);
+ /* scan through a, for each found bit: */
+ while ((current = mpz_scan1(a, current)) != ULONG_MAX)
+ {
+ /* XOR shifted b into r */
+ shift = current - shifted;
+ mpz_mul_2exp(bm, bm, shift);
+ shifted += shift;
+ mpz_xor(rm, rm, bm);
+ current++;
+ }
+
+ mpz_swap(r, rm);
+ mpz_clear(rm);
+ mpz_clear(bm);
+}
+
+/**
+ * Calculate the sum of a + b interpreted as polynoms.
+ */
+static void mpz_add_poly(mpz_t res, mpz_t a, mpz_t b)
+{
+ /* addition of polynominals is just the XOR */
+ mpz_xor(res, a, b);
+}
+
+/**
+ * Calculate the remainder of a/b interpreted as polynoms.
+ */
+static void mpz_mod_poly(mpz_t r, mpz_t a, mpz_t b)
+{
+ /* Example:
+ * a = 10001010
+ * b = 00000101
+ */
+ int a_bit, b_bit, diff;
+ mpz_t bm, am;
+
+ mpz_init_set(am, a);
+ mpz_init(bm);
+
+ a_bit = mpz_sizeinbase(a, 2);
+ b_bit = mpz_sizeinbase(b, 2);
+
+ /* don't do anything if b > a */
+ if (a_bit >= b_bit)
+ {
+ /* shift b left to align up most signaficant "1" to a:
+ * a = 10001010
+ * b = 10100000
+ */
+ mpz_mul_2exp(bm, b, a_bit - b_bit);
+ do
+ {
+ /* XOR b into a, this kills the most significant "1":
+ * a = 00101010
+ */
+ mpz_xor(am, am, bm);
+ /* find the next most significant "1" in a, and align up b:
+ * a = 00101010
+ * b = 00101000
+ */
+ diff = a_bit - mpz_sizeinbase(am, 2);
+ mpz_div_2exp(bm, bm, diff);
+ a_bit -= diff;
+ }
+ while (b_bit <= mpz_sizeinbase(bm, 2));
+ /* While b is not shifted to its original value */
+ }
+ /* after another iteration:
+ * a = 00000010
+ * which is the polynomial modulo
+ */
+
+ mpz_swap(r, am);
+ mpz_clear(am);
+ mpz_clear(bm);
+}
+
+/**
+ * Step 3 of the various fx() functions:
+ * XOR the key into the SHA1 IV
+ */
+static void step3(prf_t *prf, u_char k[AKA_K_LEN],
+ u_char payload[AKA_PAYLOAD_LEN], u_int8_t h[HASH_SIZE_SHA1])
+{
+ /* use the keyed hasher to build the hash */
+ prf->set_key(prf, chunk_create(k, AKA_K_LEN));
+ prf->get_bytes(prf, chunk_create(payload, AKA_PAYLOAD_LEN), h);
+}
+
+/**
+ * Step 4 of the various fx() functions:
+ * Polynomial whiten calculations
+ */
+static void step4(u_char x[HASH_SIZE_SHA1])
+{
+ mpz_t xm, am, bm, gm;
+
+ mpz_init(xm);
+ mpz_init(am);
+ mpz_init(bm);
+ mpz_init(gm);
+
+ mpz_import(xm, HASH_SIZE_SHA1, 1, 1, 1, 0, x);
+ mpz_import(am, sizeof(a), 1, 1, 1, 0, a);
+ mpz_import(bm, sizeof(b), 1, 1, 1, 0, b);
+ mpz_import(gm, sizeof(g), 1, 1, 1, 0, g);
+
+ mpz_mul_poly(xm, am, xm);
+ mpz_add_poly(xm, bm, xm);
+ mpz_mod_poly(xm, xm, gm);
+
+ mpz_export(x, NULL, 1, HASH_SIZE_SHA1, 1, 0, xm);
+
+ mpz_clear(xm);
+ mpz_clear(am);
+ mpz_clear(bm);
+ mpz_clear(gm);
+}
+
+/**
+ * Calculation function for f2(), f3(), f4()
+ */
+static void fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char out[AKA_MAC_LEN])
+{
+ u_char payload[AKA_PAYLOAD_LEN];
+ u_char h[HASH_SIZE_SHA1];
+ u_char i;
+
+ for (i = 0; i < 2; i++)
+ {
+ memset(payload, 0x5c, AKA_PAYLOAD_LEN);
+ payload[11] ^= f;
+ memxor(payload + 12, fmk.ptr, fmk.len);
+ memxor(payload + 24, rand, AKA_RAND_LEN);
+
+ payload[3] ^= i;
+ payload[19] ^= i;
+ payload[35] ^= i;
+ payload[51] ^= i;
+
+ step3(prf, k, payload, h);
+ step4(h);
+ memcpy(out + i * 8, h, 8);
+ }
+}
+
+/**
+ * Calculation function of f1() and f1star()
+ */
+static void f1x(prf_t *prf, u_int8_t f, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
+ u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
+{
+ /* generate MAC = f1(FMK, SQN, RAND, AMF)
+ * K is loaded into hashers IV; FMK, RAND, SQN, AMF are XORed in a 512-bit
+ * payload which gets hashed
+ */
+ u_char payload[AKA_PAYLOAD_LEN];
+ u_char h[HASH_SIZE_SHA1];
+
+ memset(payload, 0x5c, AKA_PAYLOAD_LEN);
+ payload[11] ^= f;
+ memxor(payload + 12, fmk.ptr, fmk.len);
+ memxor(payload + 16, rand, AKA_RAND_LEN);
+ memxor(payload + 34, sqn, AKA_SQN_LEN);
+ memxor(payload + 42, amf, AKA_AMF_LEN);
+
+ step3(prf, k, payload, h);
+ step4(h);
+ memcpy(mac, h, AKA_MAC_LEN);
+}
+
+/**
+ * Calculation function of f5() and f5star()
+ */
+static void f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
+{
+ u_char payload[AKA_PAYLOAD_LEN];
+ u_char h[HASH_SIZE_SHA1];
+
+ memset(payload, 0x5c, AKA_PAYLOAD_LEN);
+ payload[11] ^= f;
+ memxor(payload + 12, fmk.ptr, fmk.len);
+ memxor(payload + 16, rand, AKA_RAND_LEN);
+
+ step3(prf, k, payload, h);
+ step4(h);
+ memcpy(ak, h, AKA_AK_LEN);
+}
+
+/**
+ * Calculate MAC from RAND, SQN, AMF using K
+ */
+static void f1(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
+ u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
+{
+ f1x(this->prf, F1, k, rand, sqn, amf, mac);
+ DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN);
+}
+
+/**
+ * Calculate MACS from RAND, SQN, AMF using K
+ */
+static void f1star(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
+ u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN])
+{
+ f1x(this->prf, F1STAR, k, rand, sqn, amf, macs);
+ DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN);
+}
+
+/**
+ * Calculate RES from RAND using K
+ */
+static void f2(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX])
+{
+ fx(this->prf, F2, k, rand, res);
+ DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX);
+}
+
+/**
+ * Calculate CK from RAND using K
+ */
+static void f3(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN])
+{
+ fx(this->prf, F3, k, rand, ck);
+ DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN);
+}
+
+/**
+ * Calculate IK from RAND using K
+ */
+static void f4(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN])
+{
+ fx(this->prf, F4, k, rand, ik);
+ DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN);
+}
+
+/**
+ * Calculate AK from a RAND using K
+ */
+static void f5(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
+{
+ f5x(this->prf, F5, k, rand, ak);
+ DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN);
+}
+
+/**
+ * Calculate AKS from a RAND using K
+ */
+static void f5star(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN])
+{
+ f5x(this->prf, F5STAR, k, rand, aks);
+ DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN);
+}
+
+
+/**
+ * Implementation of eap_aka_3gpp2_functions_t.destroy.
+ */
+static void destroy(private_eap_aka_3gpp2_functions_t *this)
+{
+ this->prf->destroy(this->prf);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_aka_3gpp2_functions_t *eap_aka_3gpp2_functions_create()
+{
+ private_eap_aka_3gpp2_functions_t *this;
+
+ this = malloc_thing(private_eap_aka_3gpp2_functions_t);
+
+ this->public.f1 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]))f1;
+ this->public.f1star = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]))f1star;
+ this->public.f2 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]))f2;
+ this->public.f3 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]))f3;
+ this->public.f4 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]))f4;
+ this->public.f5 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]))f5;
+ this->public.f5star = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]))f5star;
+ this->public.destroy = (void(*)(eap_aka_3gpp2_functions_t*))destroy;
+
+ this->prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1);
+ if (!this->prf)
+ {
+ DBG1(DBG_CFG, "%N not supported, unable to use 3GPP2 algorithm",
+ pseudo_random_function_names, PRF_KEYED_SHA1);
+ free(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h
new file mode 100644
index 000000000..95c6da6a9
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_3gpp2_functions eap_aka_3gpp2_functions
+ * @{ @ingroup eap_aka_3gpp2
+ */
+
+#ifndef EAP_AKA_3GPP2_FUNCTIONS_H_
+#define EAP_AKA_3GPP2_FUNCTIONS_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+#define AKA_SQN_LEN 6
+#define AKA_K_LEN 16
+#define AKA_MAC_LEN 8
+#define AKA_AK_LEN 6
+#define AKA_AMF_LEN 2
+#define AKA_FMK_LEN 4
+
+typedef struct eap_aka_3gpp2_functions_t eap_aka_3gpp2_functions_t;
+
+/**
+ * f1-f5(), f1*() and f5*() functions from the 3GPP2 (S.S0055) standard.
+ */
+struct eap_aka_3gpp2_functions_t {
+
+ /**
+ * Calculate MAC from RAND, SQN, AMF using K.
+ *
+ * @param k secret key K
+ * @param rand random value rand
+ * @param sqn sequence number
+ * @param amf authentication management field
+ * @param mac buffer receiving mac MAC
+ */
+ void (*f1)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
+ u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]);
+
+ /**
+ * Calculate MACS from RAND, SQN, AMF using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param sqn sequence number
+ * @param amf authentication management field
+ * @param macs buffer receiving resynchronization mac MACS
+ */
+ void (*f1star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
+ u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]);
+
+ /**
+ * Calculate RES from RAND using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param res buffer receiving result RES, uses full 128 bit
+ */
+ void (*f2)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]);
+ /**
+ * Calculate CK from RAND using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param macs buffer receiving encryption key CK
+ */
+ void (*f3)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]);
+ /**
+ * Calculate IK from RAND using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param macs buffer receiving integrity key IK
+ */
+ void (*f4)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]);
+ /**
+ * Calculate AK from a RAND using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param macs buffer receiving anonymity key AK
+ */
+ void (*f5)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]);
+ /**
+ * Calculate AKS from a RAND using K
+ *
+ * @param k secret key K
+ * @param rand random value RAND
+ * @param macs buffer receiving resynchronization anonymity key AKS
+ */
+ void (*f5star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]);
+
+ /**
+ * Destroy a eap_aka_3gpp2_functions_t.
+ */
+ void (*destroy)(eap_aka_3gpp2_functions_t *this);
+};
+
+/**
+ * Create a eap_aka_3gpp2_functions instance.
+ *
+ * @return function set, NULL on error
+ */
+eap_aka_3gpp2_functions_t *eap_aka_3gpp2_functions_create();
+
+#endif /** EAP_AKA_3GPP2_FUNCTIONS_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c
new file mode 100644
index 000000000..626e83311
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008-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 "eap_aka_3gpp2_plugin.h"
+#include "eap_aka_3gpp2_card.h"
+#include "eap_aka_3gpp2_provider.h"
+#include "eap_aka_3gpp2_functions.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_aka_3gpp2_t private_eap_aka_3gpp2_t;
+
+/**
+ * Private data of an eap_aka_3gpp2_t object.
+ */
+struct private_eap_aka_3gpp2_t {
+
+ /**
+ * Public eap_aka_3gpp2_plugin_t interface.
+ */
+ eap_aka_3gpp2_plugin_t public;
+
+ /**
+ * SIM card
+ */
+ eap_aka_3gpp2_card_t *card;
+
+ /**
+ * SIM provider
+ */
+ eap_aka_3gpp2_provider_t *provider;
+
+ /**
+ * AKA functions
+ */
+ eap_aka_3gpp2_functions_t *functions;
+};
+
+/**
+ * Implementation of eap_aka_3gpp2_t.destroy.
+ */
+static void destroy(private_eap_aka_3gpp2_t *this)
+{
+ charon->sim->remove_card(charon->sim, &this->card->card);
+ charon->sim->remove_provider(charon->sim, &this->provider->provider);
+ this->card->destroy(this->card);
+ this->provider->destroy(this->provider);
+ this->functions->destroy(this->functions);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_aka_3gpp2_plugin_create()
+{
+ private_eap_aka_3gpp2_t *this = malloc_thing(private_eap_aka_3gpp2_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->functions = eap_aka_3gpp2_functions_create();
+ if (!this->functions)
+ {
+ free(this);
+ return NULL;
+ }
+ this->card = eap_aka_3gpp2_card_create(this->functions);
+ this->provider = eap_aka_3gpp2_provider_create(this->functions);
+
+ charon->sim->add_card(charon->sim, &this->card->card);
+ charon->sim->add_provider(charon->sim, &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.h
new file mode 100644
index 000000000..2ac450a7d
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_3gpp2 eap_aka_3gpp2
+ * @ingroup cplugins
+ *
+ * @defgroup eap_aka_3gpp2_plugin eap_aka_3gpp2_plugin
+ * @{ @ingroup eap_aka_3gpp2
+ */
+
+#ifndef EAP_AKA_3GPP2_PLUGIN_H_
+#define EAP_AKA_3GPP2_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_aka_3gpp2_plugin_t eap_aka_3gpp2_plugin_t;
+
+/**
+ * Plugin to provide a SIM card/provider using the 3GPP2 (S.S0055) standard.
+ *
+ * This plugin implements the standard of the 3GPP2 (S.S0055) and not the one
+ * of 3GGP, completely in software using the libgmp library..
+ * The shared key used for authentication is from ipsec.secrets. The
+ * peers ID is used to query it.
+ * The AKA mechanism uses sequence numbers to detect replay attacks. The
+ * peer stores the sequence number normally in a USIM and accepts
+ * incremental sequence numbers (incremental for lifetime of the USIM). To
+ * prevent a complex sequence number management, this implementation uses
+ * a sequence number derived from time. It is initialized to the startup
+ * time of the daemon.
+ * To enable time based SEQs, define SEQ_CHECK as 1. Default is to accept
+ * any SEQ numbers. This allows an attacker to do replay attacks. But since
+ * the server has proven his identity via IKE, such an attack is only
+ * possible between server and AAA (if any).
+ */
+struct eap_aka_3gpp2_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_AKA_3GPP2_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
new file mode 100644
index 000000000..9817fff8f
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2008-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 "eap_aka_3gpp2_provider.h"
+
+#include <daemon.h>
+#include <credentials/keys/shared_key.h>
+
+typedef struct private_eap_aka_3gpp2_provider_t private_eap_aka_3gpp2_provider_t;
+
+/**
+ * Private data of an eap_aka_3gpp2_provider_t object.
+ */
+struct private_eap_aka_3gpp2_provider_t {
+
+ /**
+ * Public eap_aka_3gpp2_provider_t interface.
+ */
+ eap_aka_3gpp2_provider_t public;
+
+ /**
+ * AKA functions
+ */
+ eap_aka_3gpp2_functions_t *f;
+
+ /**
+ * time based SQN, we use the same for all peers
+ */
+ char sqn[AKA_SQN_LEN];
+};
+
+/** Authentication management field */
+static char amf[AKA_AMF_LEN] = {0x00, 0x01};
+
+/**
+ * Get a shared key K from the credential database
+ */
+bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN])
+{
+ shared_key_t *shared;
+ chunk_t key;
+
+ shared = charon->credentials->get_shared(charon->credentials,
+ SHARED_EAP, id, NULL);
+ if (shared == NULL)
+ {
+ return FALSE;
+ }
+ key = shared->get_key(shared);
+ memset(k, '\0', AKA_K_LEN);
+ memcpy(k, key.ptr, min(key.len, AKA_K_LEN));
+ shared->destroy(shared);
+ return TRUE;
+}
+
+/**
+ * get SQN using current time
+ */
+void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset)
+{
+ timeval_t time;
+
+ gettimeofday(&time, NULL);
+ /* set sqn to an integer containing 4 bytes seconds + 2 bytes usecs */
+ time.tv_sec = htonl(time.tv_sec + offset);
+ /* usec's are never larger than 0x000f423f, so we shift the 12 first bits */
+ time.tv_usec = htonl(time.tv_usec << 12);
+ memcpy(sqn, (char*)&time.tv_sec + sizeof(time_t) - 4, 4);
+ memcpy(sqn + 4, &time.tv_usec, 2);
+}
+
+/**
+ * Implementation of usim_provider_t.get_quintuplet
+ */
+static bool get_quintuplet(private_eap_aka_3gpp2_provider_t *this,
+ identification_t *id, char rand[AKA_RAND_LEN],
+ char xres[AKA_RES_MAX], int *xres_len,
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char autn[AKA_AUTN_LEN])
+{
+ rng_t *rng;
+ char mac[AKA_MAC_LEN], ak[AKA_AK_LEN], k[AKA_K_LEN];
+
+ /* generate RAND: we use a registered RNG, not f0() proposed in S.S0055 */
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "generating RAND for AKA failed");
+ return FALSE;
+ }
+ rng->get_bytes(rng, AKA_RAND_LEN, rand);
+ rng->destroy(rng);
+
+ if (!eap_aka_3gpp2_get_k(id, k))
+ {
+ DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
+ return FALSE;
+ }
+
+ DBG3(DBG_IKE, "generated rand %b", rand, AKA_RAND_LEN);
+ DBG3(DBG_IKE, "using K %b", k, AKA_K_LEN);
+
+ /* MAC */
+ this->f->f1(this->f, k, rand, this->sqn, amf, mac);
+ /* AK */
+ this->f->f5(this->f, k, rand, ak);
+ /* XRES as expected from client */
+ this->f->f2(this->f, k, rand, xres);
+ *xres_len = AKA_RES_MAX;
+ /* AUTN = (SQN xor AK) || AMF || MAC */
+ memcpy(autn, this->sqn, AKA_SQN_LEN);
+ memxor(autn, ak, AKA_AK_LEN);
+ memcpy(autn + AKA_SQN_LEN, amf, AKA_AMF_LEN);
+ memcpy(autn + AKA_SQN_LEN + AKA_AMF_LEN, mac, AKA_MAC_LEN);
+ DBG3(DBG_IKE, "AUTN %b", autn, AKA_AUTN_LEN);
+ /* CK/IK */
+ this->f->f3(this->f, k, rand, ck);
+ this->f->f4(this->f, k, rand, ik);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of usim_provider_t.resync
+ */
+static bool resync(private_eap_aka_3gpp2_provider_t *this,
+ identification_t *id, char rand[AKA_RAND_LEN],
+ char auts[AKA_AUTS_LEN])
+{
+ char *sqn, *macs;
+ char aks[AKA_AK_LEN], k[AKA_K_LEN], amf[AKA_AMF_LEN], xmacs[AKA_MAC_LEN];
+
+ if (!eap_aka_3gpp2_get_k(id, k))
+ {
+ DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
+ return FALSE;
+ }
+
+ /* AUTHS = (AK xor SQN) | MAC */
+ sqn = auts;
+ macs = auts + AKA_SQN_LEN;
+ this->f->f5star(this->f, k, rand, aks);
+ memxor(sqn, aks, AKA_AK_LEN);
+
+ /* verify XMACS, AMF of zero is used in resynchronization */
+ memset(amf, 0, AKA_AMF_LEN);
+ this->f->f1star(this->f, k, rand, sqn, amf, xmacs);
+ if (!memeq(macs, xmacs, AKA_MAC_LEN))
+ {
+ DBG1(DBG_IKE, "received MACS does not match XMACS");
+ DBG3(DBG_IKE, "MACS %b XMACS %b",
+ macs, AKA_MAC_LEN, xmacs, AKA_MAC_LEN);
+ return FALSE;
+ }
+ /* update stored SQN to received SQN + 1 */
+ memcpy(this->sqn, sqn, AKA_SQN_LEN);
+ chunk_increment(chunk_create(this->sqn, AKA_SQN_LEN));
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_aka_3gpp2_provider_t.destroy.
+ */
+static void destroy(private_eap_aka_3gpp2_provider_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create(
+ eap_aka_3gpp2_functions_t *f)
+{
+ private_eap_aka_3gpp2_provider_t *this = malloc_thing(private_eap_aka_3gpp2_provider_t);
+
+ this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false;
+ this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))get_quintuplet;
+ this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))resync;
+ this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null;
+ this->public.destroy = (void(*)(eap_aka_3gpp2_provider_t*))destroy;
+
+ this->f = f;
+ /* use an offset to accept clock skew between client/server without resync */
+ eap_aka_3gpp2_get_sqn(this->sqn, 180);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h
new file mode 100644
index 000000000..22ac0a96e
--- /dev/null
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-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 eap_aka_3gpp2_provider eap_aka_3gpp2_provider
+ * @{ @ingroup eap_aka_3gpp2
+ */
+
+#ifndef EAP_AKA_3GPP2_PROVIDER_H_
+#define EAP_AKA_3GPP2_PROVIDER_H_
+
+#include "eap_aka_3gpp2_functions.h"
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_aka_3gpp2_provider_t eap_aka_3gpp2_provider_t;
+
+/**
+ * SIM provider implementation using a set of AKA functions.
+ */
+struct eap_aka_3gpp2_provider_t {
+
+ /**
+ * Implements sim_provider_t interface.
+ */
+ sim_provider_t provider;
+
+ /**
+ * Destroy a eap_aka_3gpp2_provider_t.
+ */
+ void (*destroy)(eap_aka_3gpp2_provider_t *this);
+};
+
+/**
+ * Create a eap_aka_3gpp2_provider instance.
+ */
+eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create(
+ eap_aka_3gpp2_functions_t *f);
+
+#endif /** EAP_AKA_3GPP2_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am
new file mode 100644
index 000000000..d8722bf9d
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-gtc.la
+endif
+
+libstrongswan_eap_gtc_la_SOURCES = \
+ eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
+
+libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version -lpam
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
new file mode 100644
index 000000000..110e1528b
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -0,0 +1,587 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_gtc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_gtc_la_LIBADD =
+am_libstrongswan_eap_gtc_la_OBJECTS = eap_gtc_plugin.lo eap_gtc.lo
+libstrongswan_eap_gtc_la_OBJECTS = \
+ $(am_libstrongswan_eap_gtc_la_OBJECTS)
+libstrongswan_eap_gtc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_gtc_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_gtc_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_gtc_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_gtc_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_gtc_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-gtc.la
+libstrongswan_eap_gtc_la_SOURCES = \
+ eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
+
+libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version -lpam
+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/eap_gtc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_gtc/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-gtc.la: $(libstrongswan_eap_gtc_la_OBJECTS) $(libstrongswan_eap_gtc_la_DEPENDENCIES)
+ $(libstrongswan_eap_gtc_la_LINK) $(am_libstrongswan_eap_gtc_la_rpath) $(libstrongswan_eap_gtc_la_OBJECTS) $(libstrongswan_eap_gtc_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_gtc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_gtc_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
new file mode 100644
index 000000000..c7f55fa70
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_gtc.h"
+
+#include <daemon.h>
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
+#include <security/pam_appl.h>
+
+#define GTC_REQUEST_MSG "password"
+#define GTC_PAM_SERVICE "login"
+
+typedef struct private_eap_gtc_t private_eap_gtc_t;
+
+/**
+ * Private data of an eap_gtc_t object.
+ */
+struct private_eap_gtc_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_gtc_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * EAP message identififier
+ */
+ u_int8_t identifier;
+};
+
+typedef struct eap_gtc_header_t eap_gtc_header_t;
+
+/**
+ * packed eap GTC header struct
+ */
+struct eap_gtc_header_t {
+ /** EAP code (REQUEST/RESPONSE) */
+ u_int8_t code;
+ /** unique message identifier */
+ u_int8_t identifier;
+ /** length of whole message */
+ u_int16_t length;
+ /** EAP type */
+ u_int8_t type;
+ /** type data */
+ u_int8_t data[];
+} __attribute__((__packed__));
+
+/**
+ * Implementation of eap_method_t.initiate for the peer
+ */
+static status_t initiate_peer(private_eap_gtc_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * PAM conv callback function
+ */
+static int auth_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, char *password)
+{
+ struct pam_response *response;
+
+ if (num_msg != 1)
+ {
+ return PAM_CONV_ERR;
+ }
+ response = malloc(sizeof(struct pam_response));
+ response->resp = strdup(password);
+ response->resp_retcode = 0;
+ *resp = response;
+ return PAM_SUCCESS;
+}
+
+/**
+ * Authenticate a username/password using PAM
+ */
+static bool authenticate(char *service, char *user, char *password)
+{
+ pam_handle_t *pamh = NULL;
+ static struct pam_conv conv;
+ int ret;
+
+ conv.conv = (void*)auth_conv;
+ conv.appdata_ptr = password;
+
+ ret = pam_start(service, user, &conv, &pamh);
+ if (ret != PAM_SUCCESS)
+ {
+ DBG1(DBG_IKE, "EAP-GTC pam_start failed: %s",
+ pam_strerror(pamh, ret));
+ return FALSE;
+ }
+ ret = pam_authenticate(pamh, 0);
+ if (ret == PAM_SUCCESS)
+ {
+ ret = pam_acct_mgmt(pamh, 0);
+ if (ret != PAM_SUCCESS)
+ {
+ DBG1(DBG_IKE, "EAP-GTC pam_acct_mgmt failed: %s",
+ pam_strerror(pamh, ret));
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP-GTC pam_authenticate failed: %s",
+ pam_strerror(pamh, ret));
+ }
+ pam_end(pamh, ret);
+ return ret == PAM_SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the server
+ */
+static status_t initiate_server(private_eap_gtc_t *this, eap_payload_t **out)
+{
+ eap_gtc_header_t *req;
+ size_t len;
+
+ len = strlen(GTC_REQUEST_MSG);
+ req = alloca(sizeof(eap_gtc_header_t) + len);
+ req->length = htons(sizeof(eap_gtc_header_t) + len);
+ req->code = EAP_REQUEST;
+ req->identifier = this->identifier;
+ req->type = EAP_GTC;
+ memcpy(req->data, GTC_REQUEST_MSG, len);
+
+ *out = eap_payload_create_data(chunk_create((void*)req,
+ sizeof(eap_gtc_header_t) + len));
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.process for the peer
+ */
+static status_t process_peer(private_eap_gtc_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ eap_gtc_header_t *res;
+ shared_key_t *shared;
+ chunk_t key;
+ size_t len;
+
+ shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP,
+ this->peer, this->server);
+ if (shared == NULL)
+ {
+ DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
+ this->peer, this->server);
+ return FAILED;
+ }
+ key = shared->get_key(shared);
+ len = key.len;
+
+ /* TODO: According to the draft we should "SASLprep" password, RFC4013. */
+
+ res = alloca(sizeof(eap_gtc_header_t) + len);
+ res->length = htons(sizeof(eap_gtc_header_t) + len);
+ res->code = EAP_RESPONSE;
+ res->identifier = in->get_identifier(in);
+ res->type = EAP_GTC;
+ memcpy(res->data, key.ptr, len);
+
+ shared->destroy(shared);
+
+ *out = eap_payload_create_data(chunk_create((void*)res,
+ sizeof(eap_gtc_header_t) + len));
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.process for the server
+ */
+static status_t process_server(private_eap_gtc_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ chunk_t data, encoding;
+ char *user, *password, *service, *pos;
+
+ data = chunk_skip(in->get_data(in), 5);
+ if (this->identifier != in->get_identifier(in) || !data.len)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-GTC message");
+ return FAILED;
+ }
+
+ encoding = this->peer->get_encoding(this->peer);
+ /* if a RFC822_ADDR id is provided, we use the username part only */
+ pos = memchr(encoding.ptr, '@', encoding.len);
+ if (pos)
+ {
+ encoding.len = (u_char*)pos - encoding.ptr;
+ }
+ user = alloca(encoding.len + 1);
+ memcpy(user, encoding.ptr, encoding.len);
+ user[encoding.len] = '\0';
+
+ password = alloca(data.len + 1);
+ memcpy(password, data.ptr, data.len);
+ password[data.len] = '\0';
+
+ service = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-gtc.pam_service", GTC_PAM_SERVICE);
+
+ if (!authenticate(service, user, password))
+ {
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_gtc_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_GTC;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_gtc_t *this, chunk_t *msk)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_gtc_t *this)
+{
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_gtc_t *this)
+{
+ this->peer->destroy(this->peer);
+ this->server->destroy(this->server);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_gtc_t *this = malloc_thing(private_eap_gtc_t);
+
+ this->public.eap_method_interface.initiate = NULL;
+ this->public.eap_method_interface.process = NULL;
+ this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ /* private data */
+ this->peer = peer->clone(peer);
+ this->server = server->clone(server);
+ this->identifier = 0;
+
+ return this;
+}
+
+/*
+ * see header
+ */
+eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *peer)
+{
+ private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
+
+ /* generate a non-zero identifier */
+ do {
+ this->identifier = random();
+ } while (!this->identifier);
+
+ return &this->public;
+}
+
+/*
+ * see header
+ */
+eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer)
+{
+ private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.h b/src/libcharon/plugins/eap_gtc/eap_gtc.h
new file mode 100644
index 000000000..2eb8482f8
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.h
@@ -0,0 +1,60 @@
+/*
+ * 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 eap_gtc_i eap_gtc
+ * @{ @ingroup eap_gtc
+ */
+
+#ifndef EAP_GTC_H_
+#define EAP_GTC_H_
+
+typedef struct eap_gtc_t eap_gtc_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP-GTC.
+ *
+ * This implementation of draft-sheffer-ikev2-gtc-00.txt uses PAM to
+ * verify user credentials.
+ */
+struct eap_gtc_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t eap_method_interface;
+};
+
+/**
+ * Creates the EAP method EAP-GTC acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_gtc_t object
+ */
+eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *peer);
+
+/**
+ * Creates the EAP method EAP-GTC acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_gtc_t object
+ */
+eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer);
+
+#endif /** EAP_GTC_H_ @}*/
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c
new file mode 100644
index 000000000..91ba84b3d
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#include "eap_gtc_plugin.h"
+
+#include "eap_gtc.h"
+
+#include <daemon.h>
+
+/* missing in cababilities.h */
+#define CAP_AUDIT_WRITE 29
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_gtc_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_gtc_create_server);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_gtc_create_peer);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_gtc_plugin_create()
+{
+ eap_gtc_plugin_t *this = malloc_thing(eap_gtc_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ /* required for PAM authentication */
+ charon->keep_cap(charon, CAP_AUDIT_WRITE);
+
+ charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_SERVER,
+ (eap_constructor_t)eap_gtc_create_server);
+ charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_PEER,
+ (eap_constructor_t)eap_gtc_create_peer);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.h b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.h
new file mode 100644
index 000000000..9c4052a6d
--- /dev/null
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_gtc eap_gtc
+ * @ingroup cplugins
+ *
+ * @defgroup eap_gtc_plugin eap_gtc_plugin
+ * @{ @ingroup eap_gtc
+ */
+
+#ifndef EAP_GTC_PLUGIN_H_
+#define EAP_GTC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_gtc_plugin_t eap_gtc_plugin_t;
+
+/**
+ * EAP-GTC plugin
+ */
+struct eap_gtc_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_GTC_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_identity/Makefile.am b/src/libcharon/plugins/eap_identity/Makefile.am
new file mode 100644
index 000000000..2a7c764b0
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-identity.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-identity.la
+endif
+
+libstrongswan_eap_identity_la_SOURCES = \
+ eap_identity_plugin.h eap_identity_plugin.c eap_identity.h eap_identity.c
+
+libstrongswan_eap_identity_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
new file mode 100644
index 000000000..bbb987dd6
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -0,0 +1,589 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_identity
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_identity_la_LIBADD =
+am_libstrongswan_eap_identity_la_OBJECTS = eap_identity_plugin.lo \
+ eap_identity.lo
+libstrongswan_eap_identity_la_OBJECTS = \
+ $(am_libstrongswan_eap_identity_la_OBJECTS)
+libstrongswan_eap_identity_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_identity_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_identity_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_identity_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_identity_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_identity_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-identity.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-identity.la
+libstrongswan_eap_identity_la_SOURCES = \
+ eap_identity_plugin.h eap_identity_plugin.c eap_identity.h eap_identity.c
+
+libstrongswan_eap_identity_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_identity/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_identity/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-identity.la: $(libstrongswan_eap_identity_la_OBJECTS) $(libstrongswan_eap_identity_la_DEPENDENCIES)
+ $(libstrongswan_eap_identity_la_LINK) $(am_libstrongswan_eap_identity_la_rpath) $(libstrongswan_eap_identity_la_OBJECTS) $(libstrongswan_eap_identity_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_identity.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_identity_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_identity/eap_identity.c b/src/libcharon/plugins/eap_identity/eap_identity.c
new file mode 100644
index 000000000..ab082a955
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/eap_identity.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2007-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.
+ */
+
+#include "eap_identity.h"
+
+#include <daemon.h>
+#include <library.h>
+
+typedef struct private_eap_identity_t private_eap_identity_t;
+
+/**
+ * Private data of an eap_identity_t object.
+ */
+struct private_eap_identity_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_identity_t public;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * received identity chunk
+ */
+ chunk_t identity;
+};
+
+typedef struct eap_identity_header_t eap_identity_header_t;
+
+/**
+ * packed EAP Identity header struct
+ */
+struct eap_identity_header_t {
+ /** EAP code (REQUEST/RESPONSE) */
+ u_int8_t code;
+ /** unique message identifier */
+ u_int8_t identifier;
+ /** length of whole message */
+ u_int16_t length;
+ /** EAP type */
+ u_int8_t type;
+ /** identity data */
+ u_int8_t data[];
+} __attribute__((__packed__));
+
+/**
+ * Implementation of eap_method_t.process for the peer
+ */
+static status_t process_peer(private_eap_identity_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ chunk_t id;
+ eap_identity_header_t *hdr;
+ size_t len;
+
+ id = this->peer->get_encoding(this->peer);
+ len = sizeof(eap_identity_header_t) + id.len;
+
+ hdr = alloca(len);
+ hdr->code = EAP_RESPONSE;
+ hdr->identifier = in->get_identifier(in);
+ hdr->length = htons(len);
+ hdr->type = EAP_IDENTITY;
+ memcpy(hdr->data, id.ptr, id.len);
+
+ *out = eap_payload_create_data(chunk_create((u_char*)hdr, len));
+ return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the peer
+ */
+static status_t initiate_peer(private_eap_identity_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.process for the server
+ */
+static status_t process_server(private_eap_identity_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ chunk_t data;
+
+ data = chunk_skip(in->get_data(in), 5);
+ if (data.len)
+ {
+ this->identity = chunk_clone(data);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the server
+ */
+static status_t initiate_server(private_eap_identity_t *this, eap_payload_t **out)
+{
+ eap_identity_header_t hdr;
+
+ hdr.code = EAP_REQUEST;
+ hdr.identifier = 0;
+ hdr.length = htons(sizeof(eap_identity_header_t));
+ hdr.type = EAP_IDENTITY;
+
+ *out = eap_payload_create_data(chunk_create((u_char*)&hdr,
+ sizeof(eap_identity_header_t)));
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_IDENTITY;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_identity_t *this, chunk_t *msk)
+{
+ if (this->identity.ptr)
+ {
+ *msk = this->identity;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_identity_t *this)
+{
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_identity_t *this)
+{
+ this->peer->destroy(this->peer);
+ free(this->identity.ptr);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_eap_identity_t *eap_identity_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_identity_t *this = malloc_thing(private_eap_identity_t);
+
+ this->public.eap_method_interface.initiate = NULL;
+ this->public.eap_method_interface.process = NULL;
+ this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->peer = peer->clone(peer);
+ this->identity = chunk_empty;
+
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+eap_identity_t *eap_identity_create_peer(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_identity_t *this = eap_identity_create(server, peer);
+
+ /* public functions */
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+eap_identity_t *eap_identity_create_server(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_identity_t *this = eap_identity_create(server, peer);
+
+ /* public functions */
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_identity/eap_identity.h b/src/libcharon/plugins/eap_identity/eap_identity.h
new file mode 100644
index 000000000..7364a8bda
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/eap_identity.h
@@ -0,0 +1,59 @@
+/*
+ * 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 eap_identity_i eap_identity
+ * @{ @ingroup eap_identity
+ */
+
+#ifndef EAP_IDENTITY_H_
+#define EAP_IDENTITY_H_
+
+typedef struct eap_identity_t eap_identity_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP Identity.
+ */
+struct eap_identity_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t eap_method_interface;
+};
+
+/**
+ * Creates the EAP method EAP Identity, acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_identity_t object
+ */
+eap_identity_t *eap_identity_create_server(identification_t *server,
+ identification_t *peer);
+
+/**
+ * Creates the EAP method EAP Identity, acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_identity_t object
+ */
+eap_identity_t *eap_identity_create_peer(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_IDENTITY_H_ @}*/
diff --git a/src/libcharon/plugins/eap_identity/eap_identity_plugin.c b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c
new file mode 100644
index 000000000..082997154
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#include "eap_identity_plugin.h"
+
+#include "eap_identity.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_identity_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_identity_create_server);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_identity_create_peer);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_identity_plugin_create()
+{
+ eap_identity_plugin_t *this = malloc_thing(eap_identity_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_SERVER,
+ (eap_constructor_t)eap_identity_create_server);
+ charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER,
+ (eap_constructor_t)eap_identity_create_peer);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_identity/eap_identity_plugin.h b/src/libcharon/plugins/eap_identity/eap_identity_plugin.h
new file mode 100644
index 000000000..274156a1b
--- /dev/null
+++ b/src/libcharon/plugins/eap_identity/eap_identity_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_identity eap_identity
+ * @ingroup cplugins
+ *
+ * @defgroup eap_identity_plugin eap_identity_plugin
+ * @{ @ingroup eap_identity
+ */
+
+#ifndef EAP_IDENTITY_PLUGIN_H_
+#define EAP_IDENTITY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_identity_plugin_t eap_identity_plugin_t;
+
+/**
+ * EAP-IDENTITY plugin.
+ */
+struct eap_identity_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_IDENTITY_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_md5/Makefile.am b/src/libcharon/plugins/eap_md5/Makefile.am
new file mode 100644
index 000000000..e9936c925
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-md5.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-md5.la
+endif
+
+libstrongswan_eap_md5_la_SOURCES = \
+ eap_md5_plugin.h eap_md5_plugin.c eap_md5.h eap_md5.c
+
+libstrongswan_eap_md5_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
new file mode 100644
index 000000000..943811604
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -0,0 +1,587 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_md5
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_md5_la_LIBADD =
+am_libstrongswan_eap_md5_la_OBJECTS = eap_md5_plugin.lo eap_md5.lo
+libstrongswan_eap_md5_la_OBJECTS = \
+ $(am_libstrongswan_eap_md5_la_OBJECTS)
+libstrongswan_eap_md5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_md5_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_md5_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_md5_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_md5_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_md5_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-md5.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-md5.la
+libstrongswan_eap_md5_la_SOURCES = \
+ eap_md5_plugin.h eap_md5_plugin.c eap_md5.h eap_md5.c
+
+libstrongswan_eap_md5_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_md5/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_md5/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-md5.la: $(libstrongswan_eap_md5_la_OBJECTS) $(libstrongswan_eap_md5_la_DEPENDENCIES)
+ $(libstrongswan_eap_md5_la_LINK) $(am_libstrongswan_eap_md5_la_rpath) $(libstrongswan_eap_md5_la_OBJECTS) $(libstrongswan_eap_md5_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_md5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_md5_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
new file mode 100644
index 000000000..0eda8f755
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_md5.h"
+
+#include <daemon.h>
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
+typedef struct private_eap_md5_t private_eap_md5_t;
+
+/**
+ * Private data of an eap_md5_t object.
+ */
+struct private_eap_md5_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_md5_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * challenge sent by the server
+ */
+ chunk_t challenge;
+
+ /**
+ * EAP message identififier
+ */
+ u_int8_t identifier;
+};
+
+typedef struct eap_md5_header_t eap_md5_header_t;
+
+/**
+ * packed eap MD5 header struct
+ */
+struct eap_md5_header_t {
+ /** EAP code (REQUEST/RESPONSE) */
+ u_int8_t code;
+ /** unique message identifier */
+ u_int8_t identifier;
+ /** length of whole message */
+ u_int16_t length;
+ /** EAP type */
+ u_int8_t type;
+ /** length of value (challenge) */
+ u_int8_t value_size;
+ /** actual value */
+ u_int8_t value[];
+} __attribute__((__packed__));
+
+#define CHALLENGE_LEN 16
+#define PAYLOAD_LEN (CHALLENGE_LEN + sizeof(eap_md5_header_t))
+
+/**
+ * Hash the challenge string, create response
+ */
+static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response,
+ identification_t *me, identification_t *other)
+{
+ shared_key_t *shared;
+ chunk_t concat;
+ hasher_t *hasher;
+
+ shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP,
+ me, other);
+ if (shared == NULL)
+ {
+ DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'", me, other);
+ return NOT_FOUND;
+ }
+ concat = chunk_cata("ccc", chunk_from_thing(this->identifier),
+ shared->get_key(shared), this->challenge);
+ shared->destroy(shared);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MD5 failed, MD5 not supported");
+ return FAILED;
+ }
+ hasher->allocate_hash(hasher, concat, response);
+ hasher->destroy(hasher);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the peer
+ */
+static status_t initiate_peer(private_eap_md5_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the server
+ */
+static status_t initiate_server(private_eap_md5_t *this, eap_payload_t **out)
+{
+ rng_t *rng;
+ eap_md5_header_t *req;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge);
+ rng->destroy(rng);
+
+ req = alloca(PAYLOAD_LEN);
+ req->length = htons(PAYLOAD_LEN);
+ req->code = EAP_REQUEST;
+ req->identifier = this->identifier;
+ req->type = EAP_MD5;
+ req->value_size = this->challenge.len;
+ memcpy(req->value, this->challenge.ptr, this->challenge.len);
+
+ *out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.process for the peer
+ */
+static status_t process_peer(private_eap_md5_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ chunk_t response;
+ chunk_t data;
+ eap_md5_header_t *req;
+
+ this->identifier = in->get_identifier(in);
+ data = in->get_data(in);
+ this->challenge = chunk_clone(chunk_skip(data, 6));
+ if (data.len < 6 || this->challenge.len < *(data.ptr + 5))
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MD5 message");
+ return FAILED;
+ }
+ if (hash_challenge(this, &response, this->peer, this->server) != SUCCESS)
+ {
+ return FAILED;
+ }
+ req = alloca(PAYLOAD_LEN);
+ req->length = htons(PAYLOAD_LEN);
+ req->code = EAP_RESPONSE;
+ req->identifier = this->identifier;
+ req->type = EAP_MD5;
+ req->value_size = response.len;
+ memcpy(req->value, response.ptr, response.len);
+ chunk_free(&response);
+
+ *out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.process for the server
+ */
+static status_t process_server(private_eap_md5_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ chunk_t response, expected;
+ chunk_t data;
+
+ if (this->identifier != in->get_identifier(in))
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MD5 message");
+ return FAILED;
+ }
+ if (hash_challenge(this, &expected, this->server, this->peer) != SUCCESS)
+ {
+ return FAILED;
+ }
+ data = in->get_data(in);
+ response = chunk_skip(data, 6);
+
+ if (response.len < expected.len ||
+ !memeq(response.ptr, expected.ptr, expected.len))
+ {
+ chunk_free(&expected);
+ DBG1(DBG_IKE, "EAP-MD5 verification failed");
+ return FAILED;
+ }
+ chunk_free(&expected);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_md5_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_MD5;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_md5_t *this, chunk_t *msk)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_md5_t *this)
+{
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_md5_t *this)
+{
+ this->peer->destroy(this->peer);
+ this->server->destroy(this->server);
+ chunk_free(&this->challenge);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_eap_md5_t *eap_md5_create_generic(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_md5_t *this = malloc_thing(private_eap_md5_t);
+
+ this->public.eap_method_interface.initiate = NULL;
+ this->public.eap_method_interface.process = NULL;
+ this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ /* private data */
+ this->peer = peer->clone(peer);
+ this->server = server->clone(server);
+ this->challenge = chunk_empty;
+ this->identifier = 0;
+
+ return this;
+}
+
+/*
+ * see header
+ */
+eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer)
+{
+ private_eap_md5_t *this = eap_md5_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
+
+ /* generate a non-zero identifier */
+ do {
+ this->identifier = random();
+ } while (!this->identifier);
+
+ return &this->public;
+}
+
+/*
+ * see header
+ */
+eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
+{
+ private_eap_md5_t *this = eap_md5_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.h b/src/libcharon/plugins/eap_md5/eap_md5.h
new file mode 100644
index 000000000..3cff0dd79
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/eap_md5.h
@@ -0,0 +1,57 @@
+/*
+ * 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 eap_md5_i eap_md5
+ * @{ @ingroup eap_md5
+ */
+
+#ifndef EAP_MD5_H_
+#define EAP_MD5_H_
+
+typedef struct eap_md5_t eap_md5_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP-MD5 (CHAP).
+ */
+struct eap_md5_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t eap_method_interface;
+};
+
+/**
+ * Creates the EAP method EAP-MD5 acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_md5_t object
+ */
+eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer);
+
+/**
+ * Creates the EAP method EAP-MD5 acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_md5_t object
+ */
+eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer);
+
+#endif /** EAP_MD5_H_ @}*/
diff --git a/src/libcharon/plugins/eap_md5/eap_md5_plugin.c b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c
new file mode 100644
index 000000000..e716dc6e8
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#include "eap_md5_plugin.h"
+
+#include "eap_md5.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_md5_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_md5_create_server);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_md5_create_peer);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_md5_plugin_create()
+{
+ eap_md5_plugin_t *this = malloc_thing(eap_md5_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_SERVER,
+ (eap_constructor_t)eap_md5_create_server);
+ charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_PEER,
+ (eap_constructor_t)eap_md5_create_peer);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_md5/eap_md5_plugin.h b/src/libcharon/plugins/eap_md5/eap_md5_plugin.h
new file mode 100644
index 000000000..e5e1a6e94
--- /dev/null
+++ b/src/libcharon/plugins/eap_md5/eap_md5_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_md5 eap_md5
+ * @ingroup cplugins
+ *
+ * @defgroup eap_md5_plugin eap_md5_plugin
+ * @{ @ingroup eap_md5
+ */
+
+#ifndef EAP_MD5_PLUGIN_H_
+#define EAP_MD5_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_md5_plugin_t eap_md5_plugin_t;
+
+/**
+ * EAP-MD5 plugin
+ */
+struct eap_md5_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_MD5_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.am b/src/libcharon/plugins/eap_mschapv2/Makefile.am
new file mode 100644
index 000000000..b9555b3c1
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-mschapv2.la
+endif
+
+libstrongswan_eap_mschapv2_la_SOURCES = \
+ eap_mschapv2_plugin.h eap_mschapv2_plugin.c \
+ eap_mschapv2.h eap_mschapv2.c
+
+libstrongswan_eap_mschapv2_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
new file mode 100644
index 000000000..2f6c65df4
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_mschapv2
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_mschapv2_la_LIBADD =
+am_libstrongswan_eap_mschapv2_la_OBJECTS = eap_mschapv2_plugin.lo \
+ eap_mschapv2.lo
+libstrongswan_eap_mschapv2_la_OBJECTS = \
+ $(am_libstrongswan_eap_mschapv2_la_OBJECTS)
+libstrongswan_eap_mschapv2_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_mschapv2_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_mschapv2_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_mschapv2_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_mschapv2_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_mschapv2_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-mschapv2.la
+libstrongswan_eap_mschapv2_la_SOURCES = \
+ eap_mschapv2_plugin.h eap_mschapv2_plugin.c \
+ eap_mschapv2.h eap_mschapv2.c
+
+libstrongswan_eap_mschapv2_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_mschapv2/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_mschapv2/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-mschapv2.la: $(libstrongswan_eap_mschapv2_la_OBJECTS) $(libstrongswan_eap_mschapv2_la_DEPENDENCIES)
+ $(libstrongswan_eap_mschapv2_la_LINK) $(am_libstrongswan_eap_mschapv2_la_rpath) $(libstrongswan_eap_mschapv2_la_OBJECTS) $(libstrongswan_eap_mschapv2_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_mschapv2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_mschapv2_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
new file mode 100644
index 000000000..c1ccf72eb
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -0,0 +1,1250 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2010 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 "eap_mschapv2.h"
+
+#include <ctype.h>
+#include <unistd.h>
+
+#include <daemon.h>
+#include <library.h>
+#include <utils/enumerator.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/hashers/hasher.h>
+
+typedef struct private_eap_mschapv2_t private_eap_mschapv2_t;
+
+/**
+ * Private data of an eap_mschapv2_t object.
+ */
+struct private_eap_mschapv2_t
+{
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_mschapv2_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * challenge sent by the server
+ */
+ chunk_t challenge;
+
+ /**
+ * generated NT-Response
+ */
+ chunk_t nt_response;
+
+ /**
+ * generated Authenticator Response
+ */
+ chunk_t auth_response;
+
+ /**
+ * generated MSK
+ */
+ chunk_t msk;
+
+ /**
+ * EAP message identifier
+ */
+ u_int8_t identifier;
+
+ /**
+ * MS-CHAPv2-ID (session ID, increases with each retry)
+ */
+ u_int8_t mschapv2id;
+
+ /**
+ * Number of retries
+ */
+ int retries;
+};
+
+/**
+ * OpCodes
+ */
+enum mschapv2_opcode_t
+{
+ MSCHAPV2_CHALLENGE = 1,
+ MSCHAPV2_RESPONSE = 2,
+ MSCHAPV2_SUCCESS = 3,
+ MSCHAPV2_FAILURE = 4,
+ MSCHAPV2_CHANGE_PASSWORD = 7,
+};
+
+/**
+ * Names for OpCodes
+ */
+ENUM_BEGIN(mschapv2_opcode_names, MSCHAPV2_CHALLENGE, MSCHAPV2_FAILURE,
+ "CHALLENGE",
+ "RESPONSE",
+ "SUCCESS",
+ "FAILURE");
+ENUM_NEXT(mschapv2_opcode_names, MSCHAPV2_CHANGE_PASSWORD, MSCHAPV2_CHANGE_PASSWORD, MSCHAPV2_FAILURE,
+ "CHANGE_PASSWORD");
+ENUM_END(mschapv2_opcode_names, MSCHAPV2_CHANGE_PASSWORD);
+
+/**
+ * Error codes
+ */
+enum mschapv2_error_t
+{
+ ERROR_RESTRICTED_LOGON_HOURS = 646,
+ ERROR_ACCT_DISABLED = 647,
+ ERROR_PASSWD_EXPIRED = 648,
+ ERROR_NO_DIALIN_PERMISSION = 649,
+ ERROR_AUTHENTICATION_FAILURE = 691,
+ ERROR_CHANGING_PASSWORD = 709,
+};
+
+/**
+ * Names for error codes
+ */
+ENUM_BEGIN(mschapv2_error_names, ERROR_RESTRICTED_LOGON_HOURS, ERROR_NO_DIALIN_PERMISSION,
+ "ERROR_RESTRICTED_LOGON_HOURS",
+ "ERROR_ACCT_DISABLED",
+ "ERROR_PASSWD_EXPIRED",
+ "ERROR_NO_DIALIN_PERMISSION");
+ENUM_NEXT(mschapv2_error_names, ERROR_AUTHENTICATION_FAILURE, ERROR_AUTHENTICATION_FAILURE, ERROR_NO_DIALIN_PERMISSION,
+ "ERROR_AUTHENTICATION_FAILURE");
+ENUM_NEXT(mschapv2_error_names, ERROR_CHANGING_PASSWORD, ERROR_CHANGING_PASSWORD, ERROR_AUTHENTICATION_FAILURE,
+ "ERROR_CHANGING_PASSWORD");
+ENUM_END(mschapv2_error_names, ERROR_CHANGING_PASSWORD);
+
+/* Length of the challenge */
+#define CHALLENGE_LEN 16
+/* Length of the response (see eap_mschapv2_response_t) */
+#define RESPONSE_LEN 49
+/* Length of the authenticator response string ("S=<...>") */
+#define AUTH_RESPONSE_LEN 42
+/* Name we send as authenticator */
+#define MSCHAPV2_HOST_NAME "strongSwan"
+/* Message sent on success */
+#define SUCCESS_MESSAGE " M=Welcome2strongSwan"
+/* Message sent on failure */
+#define FAILURE_MESSAGE "E=691 R=1 C="
+/* Length of the complete failure message */
+#define FAILURE_MESSAGE_LEN (sizeof(FAILURE_MESSAGE) + CHALLENGE_LEN * 2)
+
+/* Number of seconds to delay retries */
+#define RETRY_DELAY 2
+/* Maximum number of retries */
+#define MAX_RETRIES 2
+
+typedef struct eap_mschapv2_header_t eap_mschapv2_header_t;
+typedef struct eap_mschapv2_challenge_t eap_mschapv2_challenge_t;
+typedef struct eap_mschapv2_response_t eap_mschapv2_response_t;
+
+/**
+ * packed EAP-MS-CHAPv2 header struct
+ */
+struct eap_mschapv2_header_t
+{
+ /** EAP code (REQUEST/RESPONSE) */
+ u_int8_t code;
+ /** unique message identifier */
+ u_int8_t identifier;
+ /** length of whole message */
+ u_int16_t length;
+ /** EAP type */
+ u_int8_t type;
+ /** MS-CHAPv2 OpCode */
+ u_int8_t opcode;
+ /** MS-CHAPv2-ID (equals identifier) */
+ u_int8_t ms_chapv2_id;
+ /** MS-Length (defined as length - 5) */
+ u_int16_t ms_length;
+ /** packet data (determined by OpCode) */
+ u_int8_t data[];
+}__attribute__((__packed__));
+
+/**
+ * packed data for a MS-CHAPv2 Challenge packet
+ */
+struct eap_mschapv2_challenge_t
+{
+ /** Value-Size */
+ u_int8_t value_size;
+ /** Challenge */
+ u_int8_t challenge[CHALLENGE_LEN];
+ /** Name */
+ u_int8_t name[];
+}__attribute__((__packed__));
+
+/**
+ * packed data for a MS-CHAPv2 Response packet
+ */
+struct eap_mschapv2_response_t
+{
+ /** Value-Size */
+ u_int8_t value_size;
+ /** Response */
+ struct
+ {
+ /* Peer-Challenge*/
+ u_int8_t peer_challenge[CHALLENGE_LEN];
+ /* Reserved (=zero) */
+ u_int8_t peer_reserved[8];
+ /* NT-Response */
+ u_int8_t nt_response[24];
+ /* Flags (=zero) */
+ u_int8_t flags;
+ } response;
+ /** Name */
+ u_int8_t name[];
+}__attribute__((__packed__));
+
+/**
+ * Length of the MS-CHAPv2 header
+ */
+#define HEADER_LEN (sizeof(eap_mschapv2_header_t))
+
+/**
+ * Length of the header for MS-CHAPv2 success/failure packets (does not include
+ * MS-CHAPv2-ID and MS-Length, i.e. 3 octets)
+ */
+#define SHORT_HEADER_LEN (HEADER_LEN - 3)
+
+/**
+ * The minimum length of an MS-CHAPv2 Challenge packet (the name MUST be
+ * at least one octet)
+ */
+#define CHALLENGE_PAYLOAD_LEN (HEADER_LEN + sizeof(eap_mschapv2_challenge_t))
+
+/**
+ * The minimum length of an MS-CHAPv2 Response packet
+ */
+#define RESPONSE_PAYLOAD_LEN (HEADER_LEN + sizeof(eap_mschapv2_response_t))
+
+
+/**
+ * Expand a 56-bit key to a 64-bit DES key by adding parity bits (odd parity)
+ */
+static chunk_t ExpandDESKey(chunk_t key)
+{
+ static const u_char bitmask[] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
+ int i;
+ u_char carry = 0;
+ chunk_t expanded;
+
+ /* expand the 7 octets to 8 octets */
+ expanded = chunk_alloc(8);
+ for (i = 0; i < 7; i++)
+ {
+ expanded.ptr[i] = ((key.ptr[i] & bitmask[i]) >> i) | (carry << (8 - i));
+ carry = key.ptr[i] & ~bitmask[i];
+ }
+ expanded.ptr[7] = carry << 1;
+
+ /* add parity bits to each octet */
+ for (i = 0; i < 8; i++)
+ {
+ u_char val = expanded.ptr[i];
+ val = (val ^ (val >> 4)) & 0x0f;
+ expanded.ptr[i] |= (0x9669 >> val) & 1;
+ }
+ return expanded;
+}
+
+/**
+ * Calculate the NT password hash (i.e. hash the (unicode) password with MD4)
+ */
+static status_t NtPasswordHash(chunk_t password, chunk_t *password_hash)
+{
+ hasher_t *hasher;
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD4);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no MD4 hasher available");
+ return FAILED;
+ }
+ hasher->allocate_hash(hasher, password, password_hash);
+ hasher->destroy(hasher);
+ return SUCCESS;
+}
+
+/**
+ * Calculate the challenge hash (i.e. hash [peer_challenge | server_challenge |
+ * username (without domain part)] with SHA1)
+ */
+static status_t ChallengeHash(chunk_t peer_challenge, chunk_t server_challenge,
+ chunk_t username, chunk_t *challenge_hash)
+{
+ chunk_t concat;
+ hasher_t *hasher;
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
+ return FAILED;
+ }
+ concat = chunk_cata("ccc", peer_challenge, server_challenge, username);
+ hasher->allocate_hash(hasher, concat, challenge_hash);
+ hasher->destroy(hasher);
+ /* we need only the first 8 octets */
+ challenge_hash->len = 8;
+ return SUCCESS;
+}
+
+/**
+ * Calculate the challenge response (i.e. expand password_hash to three DES keys
+ * and then encrypt the 8-octet challenge_hash with these keys and concatenate
+ * the results).
+ */
+static status_t ChallengeResponse(chunk_t challenge_hash, chunk_t password_hash,
+ chunk_t *response)
+{
+ int i;
+ crypter_t *crypter;
+ chunk_t keys[3], z_password_hash;
+ crypter = lib->crypto->create_crypter(lib->crypto, ENCR_DES_ECB, 8);
+ if (crypter == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, DES-ECB not supported");
+ return FAILED;
+ }
+ /* prepare keys: first pad password_hash to 21 octets, these get then split
+ * into 7-octet chunks, which then get expanded into 8-octet DES keys */
+ z_password_hash = chunk_alloca(21);
+ memset(z_password_hash.ptr, 0, z_password_hash.len);
+ memcpy(z_password_hash.ptr, password_hash.ptr, password_hash.len);
+ chunk_split(z_password_hash, "mmm", 7, &keys[0], 7, &keys[1], 7, &keys[2]);
+
+ *response = chunk_alloc(24);
+ for (i = 0; i < 3; i++)
+ {
+ chunk_t expanded, encrypted;
+ expanded = ExpandDESKey(keys[i]);
+ crypter->set_key(crypter, expanded);
+ crypter->encrypt(crypter, challenge_hash, chunk_empty, &encrypted);
+ memcpy(&response->ptr[i * 8], encrypted.ptr, encrypted.len);
+ chunk_clear(&encrypted);
+ chunk_clear(&expanded);
+ }
+ crypter->destroy(crypter);
+ return SUCCESS;
+}
+
+/**
+ * Computes the authenticator response
+ */
+static status_t AuthenticatorResponse(chunk_t password_hash_hash,
+ chunk_t challenge_hash, chunk_t nt_response, chunk_t *response)
+{
+ chunk_t magic1 = chunk_from_chars(
+ 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
+ 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
+ 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74);
+ chunk_t magic2 = chunk_from_chars(
+ 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
+ 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
+ 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E);
+ chunk_t digest = chunk_empty, concat;
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
+ return FAILED;
+ }
+
+ concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
+ hasher->allocate_hash(hasher, concat, &digest);
+ concat = chunk_cata("ccc", digest, challenge_hash, magic2);
+ hasher->allocate_hash(hasher, concat, response);
+
+ hasher->destroy(hasher);
+ chunk_free(&digest);
+ return SUCCESS;
+}
+
+/**
+ * Generate the master session key according to RFC3079
+ */
+static status_t GenerateMSK(chunk_t password_hash_hash,
+ chunk_t nt_response, chunk_t *msk)
+{
+ chunk_t magic1 = chunk_from_chars(
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79);
+ chunk_t magic2 = chunk_from_chars(
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
+ 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x2e);
+ chunk_t magic3 = chunk_from_chars(
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
+ 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
+ 0x6b, 0x65, 0x79, 0x2e);
+ chunk_t shapad1 = chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ chunk_t shapad2 = chunk_from_chars(
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2);
+ chunk_t keypad = chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ chunk_t concat, master_key, master_receive_key, master_send_key;
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
+ return FAILED;
+ }
+
+ concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
+ hasher->allocate_hash(hasher, concat, &master_key);
+ master_key.len = 16;
+
+ concat = chunk_cata("cccc", master_key, shapad1, magic2, shapad2);
+ hasher->allocate_hash(hasher, concat, &master_receive_key);
+ master_receive_key.len = 16;
+
+ concat = chunk_cata("cccc", master_key, shapad1, magic3, shapad2);
+ hasher->allocate_hash(hasher, concat, &master_send_key);
+ master_send_key.len = 16;
+
+ *msk = chunk_cat("cccc", master_receive_key, master_send_key, keypad, keypad);
+
+ hasher->destroy(hasher);
+ chunk_free(&master_key);
+ chunk_free(&master_receive_key);
+ chunk_free(&master_send_key);
+ return SUCCESS;
+}
+
+static status_t GenerateStuff(private_eap_mschapv2_t *this,
+ chunk_t server_challenge, chunk_t peer_challenge,
+ chunk_t username, chunk_t nt_hash)
+{
+ status_t status = FAILED;
+ chunk_t nt_hash_hash = chunk_empty, challenge_hash = chunk_empty;
+
+ if (NtPasswordHash(nt_hash, &nt_hash_hash) != SUCCESS)
+ {
+ goto error;
+ }
+ if (ChallengeHash(peer_challenge, server_challenge, username,
+ &challenge_hash) != SUCCESS)
+ {
+ goto error;
+ }
+ if (ChallengeResponse(challenge_hash, nt_hash,
+ &this->nt_response) != SUCCESS)
+ {
+ goto error;
+ }
+ if (AuthenticatorResponse(nt_hash_hash, challenge_hash,
+ this->nt_response, &this->auth_response) != SUCCESS)
+ {
+ goto error;
+ }
+ if (GenerateMSK(nt_hash_hash, this->nt_response, &this->msk) != SUCCESS)
+ {
+ goto error;
+ }
+
+ status = SUCCESS;
+
+error:
+ chunk_free(&nt_hash_hash);
+ chunk_free(&challenge_hash);
+ return status;
+}
+
+/**
+ * Converts an ASCII string into a UTF-16 (little-endian) string
+ */
+static chunk_t ascii_to_unicode(chunk_t ascii)
+{
+ int i;
+ chunk_t unicode = chunk_alloc(ascii.len * 2);
+ for (i = 0; i < ascii.len; i++)
+ {
+ unicode.ptr[i * 2] = ascii.ptr[i];
+ unicode.ptr[i * 2 + 1] = 0;
+ }
+ return unicode;
+}
+
+/**
+ * sanitize a string for printing
+ */
+static char* sanitize(char *str)
+{
+ char *pos = str;
+
+ while (pos && *pos)
+ {
+ if (!isprint(*pos))
+ {
+ *pos = '?';
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
+ * Returns a chunk of just the username part of the given user identity.
+ * Note: the chunk points to internal data of the identification.
+ */
+static chunk_t extract_username(identification_t* identification)
+{
+ char *has_domain;
+ chunk_t id;
+ id = identification->get_encoding(identification);
+ has_domain = (char*)memchr(id.ptr, '\\', id.len);
+ if (has_domain)
+ {
+ int len;
+ has_domain++; /* skip the backslash */
+ len = id.len - ((u_char*)has_domain - id.ptr);
+ return len > 0 ? chunk_create(has_domain, len) : chunk_empty;
+ }
+ return id;
+}
+
+/**
+ * Set the ms_length field using aligned write
+ */
+static void set_ms_length(eap_mschapv2_header_t *eap, u_int16_t len)
+{
+ len = htons(len - 5);
+ memcpy(&eap->ms_length, &len, sizeof(u_int16_t));
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the peer
+ */
+static status_t initiate_peer(private_eap_mschapv2_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the server
+ */
+static status_t initiate_server(private_eap_mschapv2_t *this, eap_payload_t **out)
+{
+ rng_t *rng;
+ eap_mschapv2_header_t *eap;
+ eap_mschapv2_challenge_t *cha;
+ const char *name = MSCHAPV2_HOST_NAME;
+ u_int16_t len = CHALLENGE_PAYLOAD_LEN + sizeof(MSCHAPV2_HOST_NAME) - 1;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge);
+ rng->destroy(rng);
+
+ eap = alloca(len);
+ eap->code = EAP_REQUEST;
+ eap->identifier = this->identifier;
+ eap->length = htons(len);
+ eap->type = EAP_MSCHAPV2;
+ eap->opcode = MSCHAPV2_CHALLENGE;
+ eap->ms_chapv2_id = this->mschapv2id;
+ set_ms_length(eap, len);
+
+ cha = (eap_mschapv2_challenge_t*)eap->data;
+ cha->value_size = CHALLENGE_LEN;
+ memcpy(cha->challenge, this->challenge.ptr, this->challenge.len);
+ memcpy(cha->name, name, sizeof(MSCHAPV2_HOST_NAME) - 1);
+
+ *out = eap_payload_create_data(chunk_create((void*) eap, len));
+ return NEED_MORE;
+}
+
+static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me,
+ identification_t *other, chunk_t *nt_hash)
+{
+ shared_key_t *shared;
+ chunk_t password;
+
+ /* try to find a stored NT_HASH first */
+ shared = charon->credentials->get_shared(charon->credentials,
+ SHARED_NT_HASH, me, other);
+ if (shared )
+ {
+ *nt_hash = chunk_clone(shared->get_key(shared));
+ shared->destroy(shared);
+ return TRUE;
+ }
+
+ /* fallback to plaintext password */
+ shared = charon->credentials->get_shared(charon->credentials,
+ SHARED_EAP, me, other);
+ if (shared)
+ {
+ password = ascii_to_unicode(shared->get_key(shared));
+ shared->destroy(shared);
+
+ if (NtPasswordHash(password, nt_hash) == SUCCESS)
+ {
+ chunk_clear(&password);
+ return TRUE;
+ }
+ chunk_clear(&password);
+ }
+ return FALSE;
+}
+
+/**
+ * Process MS-CHAPv2 Challenge Requests
+ */
+static status_t process_peer_challenge(private_eap_mschapv2_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ rng_t *rng;
+ eap_mschapv2_header_t *eap;
+ eap_mschapv2_challenge_t *cha;
+ eap_mschapv2_response_t *res;
+ chunk_t data, peer_challenge, username, nt_hash;
+ u_int16_t len = RESPONSE_PAYLOAD_LEN;
+
+ data = in->get_data(in);
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ /* the name MUST be at least one octet long */
+ if (data.len < CHALLENGE_PAYLOAD_LEN + 1)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ return FAILED;
+ }
+
+ cha = (eap_mschapv2_challenge_t*)eap->data;
+
+ if (cha->value_size != CHALLENGE_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "invalid challenge size");
+ return FAILED;
+ }
+
+ this->mschapv2id = eap->ms_chapv2_id;
+ this->challenge = chunk_clone(chunk_create(cha->challenge, CHALLENGE_LEN));
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ return FAILED;
+ }
+ peer_challenge = chunk_alloca(CHALLENGE_LEN);
+ rng->get_bytes(rng, CHALLENGE_LEN, peer_challenge.ptr);
+ rng->destroy(rng);
+
+ if (!get_nt_hash(this, this->peer, this->server, &nt_hash))
+ {
+ DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'",
+ this->server, this->peer);
+ return NOT_FOUND;
+ }
+
+ username = extract_username(this->peer);
+ len += username.len;
+
+ if (GenerateStuff(this, this->challenge, peer_challenge,
+ username, nt_hash) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 generating NT-Response failed");
+ chunk_clear(&nt_hash);
+ return FAILED;
+ }
+ chunk_clear(&nt_hash);
+
+ eap = alloca(len);
+ eap->code = EAP_RESPONSE;
+ eap->identifier = this->identifier;
+ eap->length = htons(len);
+ eap->type = EAP_MSCHAPV2;
+ eap->opcode = MSCHAPV2_RESPONSE;
+ eap->ms_chapv2_id = this->mschapv2id;
+ set_ms_length(eap, len);
+
+ res = (eap_mschapv2_response_t*)eap->data;
+ res->value_size = RESPONSE_LEN;
+ memset(&res->response, 0, RESPONSE_LEN);
+ memcpy(res->response.peer_challenge, peer_challenge.ptr, peer_challenge.len);
+ memcpy(res->response.nt_response, this->nt_response.ptr, this->nt_response.len);
+
+ username = this->peer->get_encoding(this->peer);
+ memcpy(res->name, username.ptr, username.len);
+
+ *out = eap_payload_create_data(chunk_create((void*) eap, len));
+ return NEED_MORE;
+}
+
+/**
+ * Process MS-CHAPv2 Success Requests
+ */
+static status_t process_peer_success(private_eap_mschapv2_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ status_t status = FAILED;
+ enumerator_t *enumerator;
+ eap_mschapv2_header_t *eap;
+ chunk_t data, auth_string = chunk_empty;
+ char *message, *token, *msg = NULL;
+ int message_len;
+ u_int16_t len = SHORT_HEADER_LEN;
+
+ data = in->get_data(in);
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ if (data.len < AUTH_RESPONSE_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ return FAILED;
+ }
+
+ message_len = data.len - HEADER_LEN;
+ message = malloc(message_len + 1);
+ memcpy(message, eap->data, message_len);
+ message[message_len] = '\0';
+
+ /* S=<auth_string> M=<msg> */
+ enumerator = enumerator_create_token(message, " ", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (strneq(token, "S=", 2))
+ {
+ chunk_t hex;
+ token += 2;
+ if (strlen(token) != AUTH_RESPONSE_LEN - 2)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "invalid auth string");
+ goto error;
+ }
+ hex = chunk_create(token, AUTH_RESPONSE_LEN - 2);
+ auth_string = chunk_from_hex(hex, NULL);
+ }
+ else if (strneq(token, "M=", 2))
+ {
+ token += 2;
+ msg = strdup(token);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (auth_string.ptr == NULL)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "auth string missing");
+ goto error;
+ }
+
+ if (!chunk_equals(this->auth_response, auth_string))
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
+ goto error;
+ }
+
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", sanitize(msg));
+
+ eap = alloca(len);
+ eap->code = EAP_RESPONSE;
+ eap->identifier = this->identifier;
+ eap->length = htons(len);
+ eap->type = EAP_MSCHAPV2;
+ eap->opcode = MSCHAPV2_SUCCESS;
+
+ *out = eap_payload_create_data(chunk_create((void*) eap, len));
+ status = NEED_MORE;
+
+error:
+ chunk_free(&auth_string);
+ free(message);
+ free(msg);
+ return status;
+}
+
+static status_t process_peer_failure(private_eap_mschapv2_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ status_t status = FAILED;
+ enumerator_t *enumerator;
+ eap_mschapv2_header_t *eap;
+ chunk_t data;
+ char *message, *token, *msg = NULL;
+ int message_len, error, retryable;
+ chunk_t challenge = chunk_empty;
+
+ data = in->get_data(in);
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ if (data.len < 3) /* we want at least an error code: E=e */
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ return FAILED;
+ }
+
+ message_len = data.len - HEADER_LEN;
+ message = malloc(message_len + 1);
+ memcpy(message, eap->data, message_len);
+ message[message_len] = '\0';
+
+ /* E=eeeeeeeeee R=r C=cccccccccccccccccccccccccccccccc V=vvvvvvvvvv M=<msg> */
+ enumerator = enumerator_create_token(message, " ", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (strneq(token, "E=", 2))
+ {
+ token += 2;
+ error = atoi(token);
+ }
+ else if (strneq(token, "R=", 2))
+ {
+ token += 2;
+ retryable = atoi(token);
+ }
+ else if (strneq(token, "C=", 2))
+ {
+ chunk_t hex;
+ token += 2;
+ if (strlen(token) != 2 * CHALLENGE_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message:"
+ "invalid challenge");
+ goto error;
+ }
+ hex = chunk_create(token, 2 * CHALLENGE_LEN);
+ challenge = chunk_from_hex(hex, NULL);
+ }
+ else if (strneq(token, "V=", 2))
+ {
+ int version;
+ token += 2;
+ version = atoi(token);
+ }
+ else if (strneq(token, "M=", 2))
+ {
+ token += 2;
+ msg = strdup(token);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'",
+ mschapv2_error_names, error, sanitize(msg));
+
+ /**
+ * at this point, if the error is retryable, we MAY retry the authentication
+ * or MAY send a Change Password packet.
+ *
+ * if the error is not retryable (or if we do neither of the above), we
+ * SHOULD send a Failure Response packet.
+ * windows clients don't do that, and since windows server 2008 r2 behaves
+ * pretty odd if we do send a Failure Response, we just don't send one
+ * either. windows 7 actually sends a delete notify (which, according to the
+ * logs, results in an error on windows server 2008 r2).
+ *
+ * btw, windows server 2008 r2 does not send non-retryable errors for e.g.
+ * a disabled account but returns the windows error code in a notify payload
+ * of type 12345.
+ */
+
+ status = FAILED;
+
+error:
+ chunk_free(&challenge);
+ free(message);
+ free(msg);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.process for the peer
+ */
+static status_t process_peer(private_eap_mschapv2_t *this, eap_payload_t *in,
+ eap_payload_t **out)
+{
+ chunk_t data;
+ eap_mschapv2_header_t *eap;
+
+ this->identifier = in->get_identifier(in);
+ data = in->get_data(in);
+ if (data.len < SHORT_HEADER_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message");
+ return FAILED;
+ }
+
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ switch (eap->opcode)
+ {
+ case MSCHAPV2_CHALLENGE:
+ {
+ return process_peer_challenge(this, in, out);
+ }
+ case MSCHAPV2_SUCCESS:
+ {
+ return process_peer_success(this, in, out);
+ }
+ case MSCHAPV2_FAILURE:
+ {
+ return process_peer_failure(this, in, out);
+ }
+ default:
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
+ "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
+ break;
+ }
+ }
+ return FAILED;
+}
+
+/**
+ * Handles retries on the server
+ */
+static status_t process_server_retry(private_eap_mschapv2_t *this,
+ eap_payload_t **out)
+{
+ eap_mschapv2_header_t *eap;
+ rng_t *rng;
+ chunk_t hex;
+ char msg[FAILURE_MESSAGE_LEN];
+ u_int16_t len = HEADER_LEN + FAILURE_MESSAGE_LEN - 1; /* no null byte */
+
+ if (++this->retries > MAX_RETRIES)
+ {
+ /* we MAY send a Failure Request with R=0, but windows 7 does not
+ * really like that and does not respond with a Failure Response.
+ * so, to clean up our state we just fail with an EAP-Failure.
+ * this gives an unknown error on the windows side, but is also fine
+ * with the standard. */
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: "
+ "maximum number of retries reached");
+ return FAILED;
+ }
+
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed, retry (%d)", this->retries);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ return FAILED;
+ }
+ rng->get_bytes(rng, CHALLENGE_LEN, this->challenge.ptr);
+ rng->destroy(rng);
+
+ chunk_free(&this->nt_response);
+ chunk_free(&this->auth_response);
+ chunk_free(&this->msk);
+
+ eap = alloca(len);
+ eap->code = EAP_REQUEST;
+ eap->identifier = ++this->identifier;
+ eap->length = htons(len);
+ eap->type = EAP_MSCHAPV2;
+ eap->opcode = MSCHAPV2_FAILURE;
+ eap->ms_chapv2_id = this->mschapv2id++; /* increase for each retry */
+ set_ms_length(eap, len);
+
+ hex = chunk_to_hex(this->challenge, NULL, TRUE);
+ snprintf(msg, FAILURE_MESSAGE_LEN, "%s%s", FAILURE_MESSAGE, hex.ptr);
+ chunk_free(&hex);
+ memcpy(eap->data, msg, FAILURE_MESSAGE_LEN - 1); /* no null byte */
+ *out = eap_payload_create_data(chunk_create((void*) eap, len));
+
+ /* delay the response for some time to make brute-force attacks harder */
+ sleep(RETRY_DELAY);
+
+ return NEED_MORE;
+}
+
+/**
+ * Process MS-CHAPv2 Response response packets
+ */
+static status_t process_server_response(private_eap_mschapv2_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ eap_mschapv2_header_t *eap;
+ eap_mschapv2_response_t *res;
+ chunk_t data, peer_challenge, username, nt_hash;
+ identification_t *userid;
+ int name_len;
+ char buf[256];
+
+ data = in->get_data(in);
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ if (data.len < RESPONSE_PAYLOAD_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ return FAILED;
+ }
+
+ res = (eap_mschapv2_response_t*)eap->data;
+ peer_challenge = chunk_create(res->response.peer_challenge, CHALLENGE_LEN);
+
+ name_len = min(data.len - RESPONSE_PAYLOAD_LEN, 255);
+ snprintf(buf, sizeof(buf), "%.*s", name_len, res->name);
+ userid = identification_create_from_string(buf);
+ DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%Y'", userid);
+ username = extract_username(userid);
+
+ if (!get_nt_hash(this, this->server, userid, &nt_hash))
+ {
+ DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'",
+ this->server, userid);
+ /* FIXME: windows 7 always sends the username that is first entered in
+ * the username box, even, if the user changes it during retries (probably
+ * to keep consistent with the EAP-Identity).
+ * thus, we could actually fail here, because retries do not make much
+ * sense. on the other hand, an attacker could guess usernames, if the
+ * error messages were different. */
+ userid->destroy(userid);
+ return process_server_retry(this, out);
+ }
+
+ if (GenerateStuff(this, this->challenge, peer_challenge,
+ username, nt_hash) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
+ userid->destroy(userid);
+ chunk_clear(&nt_hash);
+ return FAILED;
+ }
+ userid->destroy(userid);
+ chunk_clear(&nt_hash);
+
+ if (memeq(res->response.nt_response, this->nt_response.ptr,
+ this->nt_response.len))
+ {
+ chunk_t hex;
+ char msg[AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE)];
+ u_int16_t len = HEADER_LEN + AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE);
+
+ eap = alloca(len);
+ eap->code = EAP_REQUEST;
+ eap->identifier = ++this->identifier;
+ eap->length = htons(len);
+ eap->type = EAP_MSCHAPV2;
+ eap->opcode = MSCHAPV2_SUCCESS;
+ eap->ms_chapv2_id = this->mschapv2id;
+ set_ms_length(eap, len);
+
+ hex = chunk_to_hex(this->auth_response, NULL, TRUE);
+ snprintf(msg, AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE),
+ "S=%s%s", hex.ptr, SUCCESS_MESSAGE);
+ chunk_free(&hex);
+ memcpy(eap->data, msg, AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE));
+ *out = eap_payload_create_data(chunk_create((void*) eap, len));
+ return NEED_MORE;
+ }
+
+ return process_server_retry(this, out);
+}
+
+/**
+ * Implementation of eap_method_t.process for the server
+ */
+static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in,
+ eap_payload_t **out)
+{
+ eap_mschapv2_header_t *eap;
+ chunk_t data;
+
+ if (this->identifier != in->get_identifier(in))
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "unexpected identifier");
+ return FAILED;
+ }
+
+ data = in->get_data(in);
+ if (data.len < SHORT_HEADER_LEN)
+ {
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ return FAILED;
+ }
+
+ eap = (eap_mschapv2_header_t*)data.ptr;
+
+ switch (eap->opcode)
+ {
+ case MSCHAPV2_RESPONSE:
+ {
+ return process_server_response(this, in, out);
+ }
+ case MSCHAPV2_SUCCESS:
+ {
+ return SUCCESS;
+ }
+ case MSCHAPV2_FAILURE:
+ {
+ return FAILED;
+ }
+ default:
+ {
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
+ "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
+ break;
+ }
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_mschapv2_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_MSCHAPV2;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_mschapv2_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_mschapv2_t *this)
+{
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_mschapv2_t *this)
+{
+ this->peer->destroy(this->peer);
+ this->server->destroy(this->server);
+ chunk_free(&this->challenge);
+ chunk_free(&this->nt_response);
+ chunk_free(&this->auth_response);
+ chunk_free(&this->msk);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_eap_mschapv2_t *eap_mschapv2_create_generic(identification_t *server, identification_t *peer)
+{
+ private_eap_mschapv2_t *this = malloc_thing(private_eap_mschapv2_t);
+
+ this->public.eap_method_interface.initiate = NULL;
+ this->public.eap_method_interface.process = NULL;
+ this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ /* private data */
+ this->peer = peer->clone(peer);
+ this->server = server->clone(server);
+ this->challenge = chunk_empty;
+ this->nt_response = chunk_empty;
+ this->auth_response = chunk_empty;
+ this->msk = chunk_empty;
+ this->identifier = 0;
+ this->mschapv2id = 0;
+ this->retries = 0;
+
+ return this;
+}
+
+/*
+ * see header
+ */
+eap_mschapv2_t *eap_mschapv2_create_server(identification_t *server, identification_t *peer)
+{
+ private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*, eap_payload_t**))process_server;
+
+ /* generate a non-zero identifier */
+ do
+ {
+ this->identifier = random();
+ } while (!this->identifier);
+
+ this->mschapv2id = this->identifier;
+
+ return &this->public;
+}
+
+/*
+ * see header
+ */
+eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identification_t *peer)
+{
+ private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*, eap_payload_t**))process_peer;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h
new file mode 100644
index 000000000..34cc1141e
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_mschapv2_i eap_mschapv2
+ * @{ @ingroup eap_mschapv2
+ */
+
+#ifndef EAP_MSCHAPV2_H_
+#define EAP_MSCHAPV2_H_
+
+typedef struct eap_mschapv2_t eap_mschapv2_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using EAP-MS-CHAPv2.
+ */
+struct eap_mschapv2_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t eap_method_interface;
+};
+
+/**
+ * Creates the EAP method EAP-MS-CHAPv2 acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_mschapv2_t object
+ */
+eap_mschapv2_t *eap_mschapv2_create_server(identification_t *server, identification_t *peer);
+
+/**
+ * Creates the EAP method EAP-MS-CHAPv2 acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_mschapv2_t object
+ */
+eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identification_t *peer);
+
+#endif /** EAP_MSCHAPV2_H_ @}*/
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c
new file mode 100644
index 000000000..a7b41ddbf
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_mschapv2_plugin.h"
+
+#include "eap_mschapv2.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_mschapv2_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_mschapv2_create_server);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_mschapv2_create_peer);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_mschapv2_plugin_create()
+{
+ eap_mschapv2_plugin_t *this = malloc_thing(eap_mschapv2_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_MSCHAPV2, 0, EAP_SERVER,
+ (eap_constructor_t)eap_mschapv2_create_server);
+ charon->eap->add_method(charon->eap, EAP_MSCHAPV2, 0, EAP_PEER,
+ (eap_constructor_t)eap_mschapv2_create_peer);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.h b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.h
new file mode 100644
index 000000000..f250a9d47
--- /dev/null
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_mschapv2 eap_mschapv2
+ * @ingroup cplugins
+ *
+ * @defgroup eap_mschapv2_plugin eap_mschapv2_plugin
+ * @{ @ingroup eap_mschapv2
+ */
+
+#ifndef EAP_MSCHAPV2_PLUGIN_H_
+#define EAP_MSCHAPV2_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_mschapv2_plugin_t eap_mschapv2_plugin_t;
+
+/**
+ * EAP-MS-CHAPv2 plugin
+ */
+struct eap_mschapv2_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_MSCHAPV2_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am
new file mode 100644
index 000000000..a3abd4124
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-radius.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-radius.la
+endif
+
+libstrongswan_eap_radius_la_SOURCES = \
+ eap_radius_plugin.h eap_radius_plugin.c \
+ eap_radius.h eap_radius.c \
+ radius_client.h radius_client.c \
+ radius_message.h radius_message.c
+
+libstrongswan_eap_radius_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
new file mode 100644
index 000000000..18427adef
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -0,0 +1,594 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_radius
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_radius_la_LIBADD =
+am_libstrongswan_eap_radius_la_OBJECTS = eap_radius_plugin.lo \
+ eap_radius.lo radius_client.lo radius_message.lo
+libstrongswan_eap_radius_la_OBJECTS = \
+ $(am_libstrongswan_eap_radius_la_OBJECTS)
+libstrongswan_eap_radius_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_eap_radius_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_radius_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_radius_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_radius_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_radius_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-radius.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-radius.la
+libstrongswan_eap_radius_la_SOURCES = \
+ eap_radius_plugin.h eap_radius_plugin.c \
+ eap_radius.h eap_radius.c \
+ radius_client.h radius_client.c \
+ radius_message.h radius_message.c
+
+libstrongswan_eap_radius_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_radius/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_radius/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-radius.la: $(libstrongswan_eap_radius_la_OBJECTS) $(libstrongswan_eap_radius_la_DEPENDENCIES)
+ $(libstrongswan_eap_radius_la_LINK) $(am_libstrongswan_eap_radius_la_rpath) $(libstrongswan_eap_radius_la_OBJECTS) $(libstrongswan_eap_radius_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_client.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_message.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
new file mode 100644
index 000000000..f041fda54
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -0,0 +1,312 @@
+/*
+ * 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 "eap_radius.h"
+
+#include "radius_message.h"
+#include "radius_client.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_radius_t private_eap_radius_t;
+
+/**
+ * Private data of an eap_radius_t object.
+ */
+struct private_eap_radius_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_radius_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * EAP method type we are proxying
+ */
+ eap_type_t type;
+
+ /**
+ * EAP vendor, if any
+ */
+ u_int32_t vendor;
+
+ /**
+ * EAP MSK, if method established one
+ */
+ chunk_t msk;
+
+ /**
+ * RADIUS client instance
+ */
+ radius_client_t *client;
+
+ /**
+ * TRUE to use EAP-Start, FALSE to send EAP-Identity Response directly
+ */
+ bool eap_start;
+
+ /**
+ * Prefix to prepend to EAP identity
+ */
+ char *id_prefix;
+};
+
+/**
+ * Add EAP-Identity to RADIUS message
+ */
+static void add_eap_identity(private_eap_radius_t *this,
+ radius_message_t *request)
+{
+ struct {
+ /** EAP code (REQUEST/RESPONSE) */
+ u_int8_t code;
+ /** unique message identifier */
+ u_int8_t identifier;
+ /** length of whole message */
+ u_int16_t length;
+ /** EAP type */
+ u_int8_t type;
+ /** identity data */
+ u_int8_t data[];
+ } __attribute__((__packed__)) *hdr;
+ chunk_t id, prefix;
+ size_t len;
+
+ id = this->peer->get_encoding(this->peer);
+ prefix = chunk_create(this->id_prefix, strlen(this->id_prefix));
+ len = sizeof(*hdr) + prefix.len + id.len;
+
+ hdr = alloca(len);
+ hdr->code = EAP_RESPONSE;
+ hdr->identifier = 0;
+ hdr->length = htons(len);
+ hdr->type = EAP_IDENTITY;
+ memcpy(hdr->data, prefix.ptr, prefix.len);
+ memcpy(hdr->data + prefix.len, id.ptr, id.len);
+
+ request->add(request, RAT_EAP_MESSAGE, chunk_create((u_char*)hdr, len));
+}
+
+/**
+ * Copy EAP-Message attribute from RADIUS message to an new EAP payload
+ */
+static bool radius2ike(private_eap_radius_t *this,
+ radius_message_t *msg, eap_payload_t **out)
+{
+ enumerator_t *enumerator;
+ eap_payload_t *payload;
+ chunk_t data, message = chunk_empty;
+ int type;
+
+ enumerator = msg->create_enumerator(msg);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_EAP_MESSAGE && data.len)
+ {
+ message = chunk_cat("mc", message, data);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (message.len)
+ {
+ *out = payload = eap_payload_create_data(message);
+ free(message.ptr);
+ /* apply EAP method selected by RADIUS server */
+ this->type = payload->get_type(payload, &this->vendor);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_method_t.initiate
+ */
+static status_t initiate(private_eap_radius_t *this, eap_payload_t **out)
+{
+ radius_message_t *request, *response;
+ status_t status = FAILED;
+ chunk_t username;
+
+ request = radius_message_create_request();
+ username = chunk_create(this->id_prefix, strlen(this->id_prefix));
+ username = chunk_cata("cc", username, this->peer->get_encoding(this->peer));
+ request->add(request, RAT_USER_NAME, username);
+
+ if (this->eap_start)
+ {
+ request->add(request, RAT_EAP_MESSAGE, chunk_empty);
+ }
+ else
+ {
+ add_eap_identity(this, request);
+ }
+
+ response = this->client->request(this->client, request);
+ if (response)
+ {
+ if (radius2ike(this, response, out))
+ {
+ status = NEED_MORE;
+ }
+ response->destroy(response);
+ }
+ request->destroy(request);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.process
+ */
+static status_t process(private_eap_radius_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ radius_message_t *request, *response;
+ status_t status = FAILED;
+ chunk_t data;
+
+ request = radius_message_create_request();
+ request->add(request, RAT_USER_NAME, this->peer->get_encoding(this->peer));
+ data = in->get_data(in);
+ /* fragment data suitable for RADIUS (not more than 253 bytes) */
+ while (data.len > 253)
+ {
+ request->add(request, RAT_EAP_MESSAGE, chunk_create(data.ptr, 253));
+ data = chunk_skip(data, 253);
+ }
+ request->add(request, RAT_EAP_MESSAGE, data);
+
+ response = this->client->request(this->client, request);
+ if (response)
+ {
+ switch (response->get_code(response))
+ {
+ case RMC_ACCESS_CHALLENGE:
+ if (radius2ike(this, response, out))
+ {
+ status = NEED_MORE;
+ break;
+ }
+ status = FAILED;
+ break;
+ case RMC_ACCESS_ACCEPT:
+ this->msk = this->client->decrypt_msk(this->client,
+ response, request);
+ status = SUCCESS;
+ break;
+ case RMC_ACCESS_REJECT:
+ default:
+ DBG1(DBG_CFG, "received %N from RADIUS server",
+ radius_message_code_names, response->get_code(response));
+ status = FAILED;
+ break;
+ }
+ response->destroy(response);
+ }
+ request->destroy(request);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_radius_t *this, u_int32_t *vendor)
+{
+ *vendor = this->vendor;
+ return this->type;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_radius_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_radius_t *this)
+{
+ switch (this->type)
+ {
+ case EAP_AKA:
+ case EAP_SIM:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_radius_t *this)
+{
+ this->peer->destroy(this->peer);
+ this->server->destroy(this->server);
+ this->client->destroy(this->client);
+ chunk_clear(&this->msk);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer)
+{
+ private_eap_radius_t *this = malloc_thing(private_eap_radius_t);
+
+ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
+ this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->client = radius_client_create();
+ if (!this->client)
+ {
+ free(this);
+ return NULL;
+ }
+ this->peer = peer->clone(peer);
+ this->server = server->clone(server);
+ /* initially EAP_RADIUS, but is set to the method selected by RADIUS */
+ this->type = EAP_RADIUS;
+ this->vendor = 0;
+ this->msk = chunk_empty;
+ this->eap_start = lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-radius.eap_start", FALSE);
+ this->id_prefix = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.id_prefix", "");
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.h b/src/libcharon/plugins/eap_radius/eap_radius.h
new file mode 100644
index 000000000..8eb9e8c2d
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/eap_radius.h
@@ -0,0 +1,48 @@
+/*
+ * 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 eap_radius_i eap_radius
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef EAP_RADIUS_H_
+#define EAP_RADIUS_H_
+
+typedef struct eap_radius_t eap_radius_t;
+
+#include <sa/authenticators/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface using a RADIUS server.
+ */
+struct eap_radius_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t eap_method_interface;
+};
+
+/**
+ * Create a EAP RADIUS proxy.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_radius_t object
+ */
+eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer);
+
+#endif /** EAP_RADIUS_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
new file mode 100644
index 000000000..7d2788c3e
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
@@ -0,0 +1,54 @@
+/*
+ * 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 "eap_radius_plugin.h"
+
+#include "eap_radius.h"
+#include "radius_client.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_radius_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create);
+ radius_client_cleanup();
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_radius_plugin_create()
+{
+ eap_radius_plugin_t *this;
+
+ if (!radius_client_init())
+ {
+ DBG1(DBG_CFG, "RADIUS plugin initialization failed");
+ return NULL;
+ }
+
+ this = malloc_thing(eap_radius_plugin_t);
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_RADIUS, 0,
+ EAP_SERVER, (eap_constructor_t)eap_radius_create);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h
new file mode 100644
index 000000000..f2b8b5082
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h
@@ -0,0 +1,45 @@
+/*
+ * 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 eap_radius eap_radius
+ * @ingroup cplugins
+ *
+ * @defgroup eap_radius_plugin eap_radius_plugin
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef EAP_RADIUS_PLUGIN_H_
+#define EAP_RADIUS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_radius_plugin_t eap_radius_plugin_t;
+
+/**
+ * EAP RADIUS proxy plugin.
+ *
+ * This plugin provides not a single EAP method, but a proxy to forwared
+ * EAP packets to a RADIUS server. It only provides server implementations.
+ */
+struct eap_radius_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_RADIUS_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c
new file mode 100644
index 000000000..1d1f21742
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_client.c
@@ -0,0 +1,495 @@
+/*
+ * 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 "radius_client.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <utils/linked_list.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+/**
+ * Default RADIUS server port, when not configured
+ */
+#define RADIUS_PORT 1812
+
+/**
+ * Vendor-Id of Microsoft specific attributes
+ */
+#define VENDOR_ID_MICROSOFT 311
+
+/**
+ * Microsoft specific vendor attributes
+ */
+#define MS_MPPE_SEND_KEY 16
+#define MS_MPPE_RECV_KEY 17
+
+typedef struct private_radius_client_t private_radius_client_t;
+
+typedef struct entry_t entry_t;
+
+/**
+ * A socket pool entry.
+ */
+struct entry_t {
+ /** socket file descriptor */
+ int fd;
+ /** current RADIUS identifier */
+ u_int8_t identifier;
+ /** hasher to use for response verification */
+ hasher_t *hasher;
+ /** HMAC-MD5 signer to build Message-Authenticator attribute */
+ signer_t *signer;
+ /** random number generator for RADIUS request authenticator */
+ rng_t *rng;
+};
+
+/**
+ * Private data of an radius_client_t object.
+ */
+struct private_radius_client_t {
+
+ /**
+ * Public radius_client_t interface.
+ */
+ radius_client_t public;
+
+ /**
+ * RADIUS servers State attribute
+ */
+ chunk_t state;
+};
+
+/**
+ * Global list of radius sockets, contains entry_t's
+ */
+static linked_list_t *sockets;
+
+/**
+ * mutex to lock sockets list
+ */
+static mutex_t *mutex;
+
+/**
+ * condvar to wait for sockets
+ */
+static condvar_t *condvar;
+
+/**
+ * RADIUS secret
+ */
+static chunk_t secret;
+
+/**
+ * NAS-Identifier
+ */
+static chunk_t nas_identifier;
+
+/**
+ * Clean up socket list
+ */
+void radius_client_cleanup()
+{
+ entry_t *entry;
+
+ mutex->destroy(mutex);
+ condvar->destroy(condvar);
+ while (sockets->remove_last(sockets, (void**)&entry) == SUCCESS)
+ {
+ entry->rng->destroy(entry->rng);
+ entry->hasher->destroy(entry->hasher);
+ entry->signer->destroy(entry->signer);
+ close(entry->fd);
+ free(entry);
+ }
+ sockets->destroy(sockets);
+}
+
+/**
+ * Initialize the socket list
+ */
+bool radius_client_init()
+{
+ int i, count, fd;
+ u_int16_t port;
+ entry_t *entry;
+ host_t *host;
+ char *server;
+
+ nas_identifier.ptr = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.nas_identifier", "strongSwan");
+ nas_identifier.len = strlen(nas_identifier.ptr);
+
+ secret.ptr = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.secret", NULL);
+ if (!secret.ptr)
+ {
+ DBG1(DBG_CFG, "no RADUIS secret defined");
+ return FALSE;
+ }
+ secret.len = strlen(secret.ptr);
+ server = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.server", NULL);
+ if (!server)
+ {
+ DBG1(DBG_CFG, "no RADUIS server defined");
+ return FALSE;
+ }
+ port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.port", RADIUS_PORT);
+ host = host_create_from_dns(server, 0, port);
+ if (!host)
+ {
+ return FALSE;
+ }
+ count = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.sockets", 1);
+
+ sockets = linked_list_create();
+ mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+ for (i = 0; i < count; i++)
+ {
+ fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0)
+ {
+ DBG1(DBG_CFG, "opening RADIUS socket failed");
+ host->destroy(host);
+ radius_client_cleanup();
+ return FALSE;
+ }
+ if (connect(fd, host->get_sockaddr(host),
+ *host->get_sockaddr_len(host)) < 0)
+ {
+ DBG1(DBG_CFG, "connecting RADIUS socket failed");
+ host->destroy(host);
+ radius_client_cleanup();
+ return FALSE;
+ }
+ entry = malloc_thing(entry_t);
+ entry->fd = fd;
+ /* we use per-socket crypto elements: this reduces overhead, but
+ * is still thread-save. */
+ entry->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ entry->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
+ entry->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!entry->hasher || !entry->signer || !entry->rng)
+ {
+ DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required");
+ DESTROY_IF(entry->hasher);
+ DESTROY_IF(entry->signer);
+ DESTROY_IF(entry->rng);
+ free(entry);
+ host->destroy(host);
+ radius_client_cleanup();
+ return FALSE;
+ }
+ entry->signer->set_key(entry->signer, secret);
+ /* we use a random identifier, helps if we restart often (testing) */
+ entry->identifier = random();
+ sockets->insert_last(sockets, entry);
+ }
+ host->destroy(host);
+ return TRUE;
+}
+
+/**
+ * Get a socket from the pool, block if none available
+ */
+static entry_t* get_socket()
+{
+ entry_t *entry;
+
+ mutex->lock(mutex);
+ while (sockets->remove_first(sockets, (void**)&entry) != SUCCESS)
+ {
+ condvar->wait(condvar, mutex);
+ }
+ mutex->unlock(mutex);
+ return entry;
+}
+
+/**
+ * Release a socket to the pool
+ */
+static void put_socket(entry_t *entry)
+{
+ mutex->lock(mutex);
+ sockets->insert_last(sockets, entry);
+ mutex->unlock(mutex);
+ condvar->signal(condvar);
+}
+
+/**
+ * Save the state attribute to include in further request
+ */
+static void save_state(private_radius_client_t *this, radius_message_t *msg)
+{
+ enumerator_t *enumerator;
+ int type;
+ chunk_t data;
+
+ enumerator = msg->create_enumerator(msg);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_STATE)
+ {
+ free(this->state.ptr);
+ this->state = chunk_clone(data);
+ enumerator->destroy(enumerator);
+ return;
+ }
+ }
+ enumerator->destroy(enumerator);
+ /* no state attribute found, remove state */
+ chunk_free(&this->state);
+}
+
+/**
+ * Implementation of radius_client_t.request
+ */
+static radius_message_t* request(private_radius_client_t *this,
+ radius_message_t *req)
+{
+ char virtual[] = {0x00,0x00,0x00,0x05};
+ entry_t *socket;
+ chunk_t data;
+ int i;
+
+ socket = get_socket();
+
+ /* set Message Identifier */
+ req->set_identifier(req, socket->identifier++);
+ /* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */
+ req->add(req, RAT_NAS_PORT_TYPE, chunk_create(virtual, sizeof(virtual)));
+ /* add our NAS-Identifier */
+ req->add(req, RAT_NAS_IDENTIFIER, nas_identifier);
+ /* add State attribute, if server sent one */
+ if (this->state.ptr)
+ {
+ req->add(req, RAT_STATE, this->state);
+ }
+ /* sign the request */
+ req->sign(req, socket->rng, socket->signer);
+
+ data = req->get_encoding(req);
+ /* timeout after 2, 3, 4, 5 seconds */
+ for (i = 2; i <= 5; i++)
+ {
+ radius_message_t *response;
+ bool retransmit = FALSE;
+ struct timeval tv;
+ char buf[4096];
+ fd_set fds;
+ int res;
+
+ if (send(socket->fd, data.ptr, data.len, 0) != data.len)
+ {
+ DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
+ put_socket(socket);
+ return NULL;
+ }
+ tv.tv_sec = i;
+ tv.tv_usec = 0;
+
+ while (TRUE)
+ {
+ FD_ZERO(&fds);
+ FD_SET(socket->fd, &fds);
+ res = select(socket->fd + 1, &fds, NULL, NULL, &tv);
+ /* TODO: updated tv to time not waited. Linux does this for us. */
+ if (res < 0)
+ { /* failed */
+ DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
+ strerror(errno));
+ break;
+ }
+ if (res == 0)
+ { /* timeout */
+ DBG1(DBG_CFG, "retransmitting RADIUS message");
+ retransmit = TRUE;
+ break;
+ }
+ res = recv(socket->fd, buf, sizeof(buf), MSG_DONTWAIT);
+ if (res <= 0)
+ {
+ DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
+ strerror(errno));
+ break;
+ }
+ response = radius_message_parse_response(chunk_create(buf, res));
+ if (response)
+ {
+ if (response->verify(response, req->get_authenticator(req),
+ secret, socket->hasher, socket->signer))
+ {
+ save_state(this, response);
+ put_socket(socket);
+ return response;
+ }
+ response->destroy(response);
+ }
+ DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+ }
+ if (!retransmit)
+ {
+ break;
+ }
+ }
+ DBG1(DBG_CFG, "RADIUS server is not responding");
+ put_socket(socket);
+ charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING);
+ return NULL;
+}
+
+/**
+ * Decrypt a MS-MPPE-Send/Recv-Key
+ */
+static chunk_t decrypt_mppe_key(private_radius_client_t *this, u_int16_t salt,
+ chunk_t C, radius_message_t *request)
+{
+ chunk_t A, R, P, seed;
+ u_char *c, *p;
+ hasher_t *hasher;
+
+ /**
+ * From RFC2548 (encryption):
+ * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1)
+ * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2)
+ * . . .
+ * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i)
+ */
+
+ if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5)
+ {
+ return chunk_empty;
+ }
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ if (!hasher)
+ {
+ return chunk_empty;
+ }
+
+ A = chunk_create((u_char*)&salt, sizeof(salt));
+ R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5);
+ P = chunk_alloca(C.len);
+ p = P.ptr;
+ c = C.ptr;
+
+ seed = chunk_cata("cc", R, A);
+
+ while (c < C.ptr + C.len)
+ {
+ /* b(i) = MD5(S + c(i-1)) */
+ hasher->get_hash(hasher, secret, NULL);
+ hasher->get_hash(hasher, seed, p);
+
+ /* p(i) = b(i) xor c(1) */
+ memxor(p, c, HASH_SIZE_MD5);
+
+ /* prepare next round */
+ seed = chunk_create(c, HASH_SIZE_MD5);
+ c += HASH_SIZE_MD5;
+ p += HASH_SIZE_MD5;
+ }
+ hasher->destroy(hasher);
+
+ /* remove truncation, first byte is key length */
+ if (*P.ptr >= P.len)
+ { /* decryption failed? */
+ return chunk_empty;
+ }
+ return chunk_clone(chunk_create(P.ptr + 1, *P.ptr));
+}
+
+/**
+ * Implementation of radius_client_t.decrypt_msk
+ */
+static chunk_t decrypt_msk(private_radius_client_t *this,
+ radius_message_t *response, radius_message_t *request)
+{
+ struct {
+ u_int32_t id;
+ u_int8_t type;
+ u_int8_t length;
+ u_int16_t salt;
+ u_int8_t key[];
+ } __attribute__((packed)) *mppe_key;
+ enumerator_t *enumerator;
+ chunk_t data, send = chunk_empty, recv = chunk_empty;
+ int type;
+
+ enumerator = response->create_enumerator(response);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_VENDOR_SPECIFIC &&
+ data.len > sizeof(*mppe_key))
+ {
+ mppe_key = (void*)data.ptr;
+ if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT &&
+ mppe_key->length == data.len - sizeof(mppe_key->id))
+ {
+ data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key));
+ if (mppe_key->type == MS_MPPE_SEND_KEY)
+ {
+ send = decrypt_mppe_key(this, mppe_key->salt, data, request);
+ }
+ if (mppe_key->type == MS_MPPE_RECV_KEY)
+ {
+ recv = decrypt_mppe_key(this, mppe_key->salt, data, request);
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (send.ptr && recv.ptr)
+ {
+ return chunk_cat("mm", recv, send);
+ }
+ chunk_clear(&send);
+ chunk_clear(&recv);
+ return chunk_empty;
+}
+
+/**
+ * Implementation of radius_client_t.destroy.
+ */
+static void destroy(private_radius_client_t *this)
+{
+ free(this->state.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+radius_client_t *radius_client_create()
+{
+ private_radius_client_t *this = malloc_thing(private_radius_client_t);
+
+ this->public.request = (radius_message_t*(*)(radius_client_t*, radius_message_t *msg))request;
+ this->public.decrypt_msk = (chunk_t(*)(radius_client_t*, radius_message_t *, radius_message_t *))decrypt_msk;
+ this->public.destroy = (void(*)(radius_client_t*))destroy;
+
+ this->state = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_radius/radius_client.h b/src/libcharon/plugins/eap_radius/radius_client.h
new file mode 100644
index 000000000..77ba94807
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_client.h
@@ -0,0 +1,88 @@
+/*
+ * 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 radius_client radius_client
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef RADIUS_CLIENT_H_
+#define RADIUS_CLIENT_H_
+
+#include "radius_message.h"
+
+typedef struct radius_client_t radius_client_t;
+
+/**
+ * RADIUS client functionality.
+ *
+ * To communicate with a RADIUS server, create a client and send messages over
+ * it. All instances share a fixed size pool of sockets. The client reserves
+ * a socket during request() and releases it afterwards.
+ */
+struct radius_client_t {
+
+ /**
+ * Send a RADIUS request and wait for the response.
+ *
+ * The client fills in RADIUS Message identifier, NAS-Identifier,
+ * NAS-Port-Type, builds a Request-Authenticator and calculates the
+ * Message-Authenticator attribute.
+ * The received response gets verified using the Response-Identifier
+ * and the Message-Authenticator attribute.
+ *
+ * @param msg RADIUS request message to send
+ * @return response, NULL if timed out/verification failed
+ */
+ radius_message_t* (*request)(radius_client_t *this, radius_message_t *msg);
+
+ /**
+ * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key.
+ *
+ * @param response RADIUS response message containing attributes
+ * @param request associated RADIUS request message
+ * @return allocated MSK, empty chunk if none found
+ */
+ chunk_t (*decrypt_msk)(radius_client_t *this, radius_message_t *response,
+ radius_message_t *request);
+
+ /**
+ * Destroy the client, release the socket.
+ */
+ void (*destroy)(radius_client_t *this);
+};
+
+/**
+ * Create a RADIUS client, acquire a socket.
+ *
+ * This call might block if the socket pool is empty.
+ *
+ * @return radius_client_t object
+ */
+radius_client_t *radius_client_create();
+
+/**
+ * Initialize the socket pool.
+ *
+ * @return TRUE if initialization successful
+ */
+bool radius_client_init();
+
+/**
+ * Cleanup the socket pool.
+ */
+void radius_client_cleanup();
+
+#endif /** RADIUS_CLIENT_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_message.c b/src/libcharon/plugins/eap_radius/radius_message.c
new file mode 100644
index 000000000..11a1d8dfc
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_message.c
@@ -0,0 +1,476 @@
+/*
+ * 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 "radius_message.h"
+
+#include <daemon.h>
+#include <crypto/hashers/hasher.h>
+
+typedef struct private_radius_message_t private_radius_message_t;
+typedef struct rmsg_t rmsg_t;
+typedef struct rattr_t rattr_t;
+
+/**
+ * RADIUS message header
+ */
+struct rmsg_t {
+ /** message code, radius_message_code_t */
+ u_int8_t code;
+ /** message identifier */
+ u_int8_t identifier;
+ /** length of Code, Identifier, Length, Authenticator and Attributes */
+ u_int16_t length;
+ /** message authenticator, MD5 hash */
+ u_int8_t authenticator[HASH_SIZE_MD5];
+ /** variable list of packed attributes */
+ u_int8_t attributes[];
+} __attribute__((packed));
+
+/**
+ * RADIUS message attribute.
+ */
+struct rattr_t {
+ /** attribute type, radius_attribute_type_t */
+ u_int8_t type;
+ /** length of the attriubte, including the Type, Length and Value fields */
+ u_int8_t length;
+ /** variable length attribute value */
+ u_int8_t value[];
+} __attribute__((packed));
+
+/**
+ * Private data of an radius_message_t object.
+ */
+struct private_radius_message_t {
+
+ /**
+ * Public radius_message_t interface.
+ */
+ radius_message_t public;
+
+ /**
+ * message data, allocated
+ */
+ rmsg_t *msg;
+};
+
+ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONSE,
+ "Access-Request",
+ "Access-Accept",
+ "Access-Reject",
+ "Accounting-Request",
+ "Accounting-Response");
+ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE,
+ "Access-Challenge");
+ENUM_END(radius_message_code_names, RMC_ACCESS_CHALLENGE);
+
+ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
+ "User-Name",
+ "User-Password",
+ "CHAP-Password",
+ "NAS-IP-Address",
+ "NAS-Port",
+ "Service-Type",
+ "Framed-Protocol",
+ "Framed-IP-Address",
+ "Framed-IP-Netmask",
+ "Framed-Routing",
+ "Filter-Id",
+ "Framed-MTU",
+ "Framed-Compression",
+ "Login-IP-Host",
+ "Login-Service",
+ "Login-TCP-Port",
+ "Unassigned",
+ "Reply-Message",
+ "Callback-Number",
+ "Callback-Id",
+ "Unassigned",
+ "Framed-Route",
+ "Framed-IPX-Network",
+ "State",
+ "Class",
+ "Vendor-Specific",
+ "Session-Timeout",
+ "Idle-Timeout",
+ "Termination-Action",
+ "Called-Station-Id",
+ "Calling-Station-Id",
+ "NAS-Identifier",
+ "Proxy-State",
+ "Login-LAT-Service",
+ "Login-LAT-Node",
+ "Login-LAT-Group",
+ "Framed-AppleTalk-Link",
+ "Framed-AppleTalk-Network",
+ "Framed-AppleTalk-Zone",
+ "Acct-Status-Type",
+ "Acct-Delay-Time",
+ "Acct-Input-Octets",
+ "Acct-Output-Octets",
+ "Acct-Session-Id",
+ "Acct-Authentic",
+ "Acct-Session-Time",
+ "Acct-Input-Packets",
+ "Acct-Output-Packets",
+ "Acct-Terminate-Cause",
+ "Acct-Multi-Session-Id",
+ "Acct-Link-Count",
+ "Acct-Input-Gigawords",
+ "Acct-Output-Gigawords",
+ "Unassigned",
+ "Event-Timestamp",
+ "Egress-VLANID",
+ "Ingress-Filters",
+ "Egress-VLAN-Name",
+ "User-Priority-Table",
+ "CHAP-Challenge",
+ "NAS-Port-Type",
+ "Port-Limit",
+ "Login-LAT-Port",
+ "Tunnel-Type",
+ "Tunnel-Medium-Type",
+ "Tunnel-Client-Endpoint",
+ "Tunnel-Server-Endpoint",
+ "Acct-Tunnel-Connection",
+ "Tunnel-Password",
+ "ARAP-Password",
+ "ARAP-Features",
+ "ARAP-Zone-Access",
+ "ARAP-Security",
+ "ARAP-Security-Data",
+ "Password-Retry",
+ "Prompt",
+ "Connect-Info",
+ "Configuration-Token",
+ "EAP-Message",
+ "Message-Authenticator",
+ "Tunnel-Private-Group-ID",
+ "Tunnel-Assignment-ID",
+ "Tunnel-Preference",
+ "ARAP-Challenge-Response",
+ "Acct-Interim-Interval",
+ "Acct-Tunnel-Packets-Lost",
+ "NAS-Port-Id",
+ "Framed-Pool",
+ "CUI",
+ "Tunnel-Client-Auth-ID",
+ "Tunnel-Server-Auth-ID",
+ "NAS-Filter-Rule",
+ "Unassigned",
+ "Originating-Line-Info",
+ "NAS-IPv6-Address",
+ "Framed-Interface-Id",
+ "Framed-IPv6-Prefix",
+ "Login-IPv6-Host",
+ "Framed-IPv6-Route",
+ "Framed-IPv6-Pool",
+ "Error-Cause",
+ "EAP-Key-Name",
+ "Digest-Response",
+ "Digest-Realm",
+ "Digest-Nonce",
+ "Digest-Response-Auth",
+ "Digest-Nextnonce",
+ "Digest-Method",
+ "Digest-URI",
+ "Digest-Qop",
+ "Digest-Algorithm",
+ "Digest-Entity-Body-Hash",
+ "Digest-CNonce",
+ "Digest-Nonce-Count",
+ "Digest-Username",
+ "Digest-Opaque",
+ "Digest-Auth-Param",
+ "Digest-AKA-Auts",
+ "Digest-Domain",
+ "Digest-Stale",
+ "Digest-HA1",
+ "SIP-AOR",
+ "Delegated-IPv6-Prefix",
+ "MIP6-Feature-Vector",
+ "MIP6-Home-Link-Prefix");
+
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+ /** implements enumerator interface */
+ enumerator_t public;
+ /** currently pointing attribute */
+ rattr_t *next;
+ /** bytes left */
+ int left;
+} attribute_enumerator_t;
+
+
+/**
+ * Implementation of attribute_enumerator_t.enumerate
+ */
+static bool attribute_enumerate(attribute_enumerator_t *this,
+ int *type, chunk_t *data)
+
+{
+ if (this->left == 0)
+ {
+ return FALSE;
+ }
+ if (this->left < sizeof(rattr_t) ||
+ this->left < this->next->length)
+ {
+ DBG1(DBG_IKE, "RADIUS message truncated");
+ return FALSE;
+ }
+ *type = this->next->type;
+ data->ptr = this->next->value;
+ data->len = this->next->length - sizeof(rattr_t);
+ this->left -= this->next->length;
+ this->next = ((void*)this->next) + this->next->length;
+ return TRUE;
+}
+
+/**
+ * Implementation of radius_message_t.create_enumerator
+ */
+static enumerator_t* create_enumerator(private_radius_message_t *this)
+{
+ attribute_enumerator_t *e;
+
+ if (ntohs(this->msg->length) < sizeof(rmsg_t) + sizeof(rattr_t))
+ {
+ return enumerator_create_empty();
+ }
+
+ e = malloc_thing(attribute_enumerator_t);
+ e->public.enumerate = (void*)attribute_enumerate;
+ e->public.destroy = (void*)free;
+ e->next = (rattr_t*)this->msg->attributes;
+ e->left = ntohs(this->msg->length) - sizeof(rmsg_t);
+ return &e->public;
+}
+
+/**
+ * Implementation of radius_message_t.add
+ */
+static void add(private_radius_message_t *this, radius_attribute_type_t type,
+ chunk_t data)
+{
+ rattr_t *attribute;
+
+ data.len = min(data.len, 253);
+ this->msg = realloc(this->msg,
+ ntohs(this->msg->length) + sizeof(rattr_t) + data.len);
+ attribute = ((void*)this->msg) + ntohs(this->msg->length);
+ attribute->type = type;
+ attribute->length = data.len + sizeof(rattr_t);
+ memcpy(attribute->value, data.ptr, data.len);
+ this->msg->length = htons(ntohs(this->msg->length) + attribute->length);
+}
+
+/**
+ * Implementation of radius_message_t.sign
+ */
+static void sign(private_radius_message_t *this, rng_t *rng, signer_t *signer)
+{
+ char buf[HASH_SIZE_MD5];
+
+ /* build Request-Authenticator */
+ rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator);
+
+ /* build Message-Authenticator attribute, using 16 null bytes */
+ memset(buf, 0, sizeof(buf));
+ add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf)));
+ signer->get_signature(signer,
+ chunk_create((u_char*)this->msg, ntohs(this->msg->length)),
+ ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5);
+}
+
+/**
+ * Implementation of radius_message_t.verify
+ */
+static bool verify(private_radius_message_t *this, u_int8_t *req_auth,
+ chunk_t secret, hasher_t *hasher, signer_t *signer)
+{
+ char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5];
+ enumerator_t *enumerator;
+ int type;
+ chunk_t data, msg;
+ bool has_eap = FALSE, has_auth = FALSE;
+
+ /* replace Response by Request Authenticator for verification */
+ memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5);
+ memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
+ msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
+
+ /* verify Response-Authenticator */
+ hasher->get_hash(hasher, msg, NULL);
+ hasher->get_hash(hasher, secret, buf);
+ if (!memeq(buf, res_auth, HASH_SIZE_MD5))
+ {
+ DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
+ return FALSE;
+ }
+
+ /* verify Message-Authenticator attribute */
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_MESSAGE_AUTHENTICATOR)
+ {
+ if (data.len != HASH_SIZE_MD5)
+ {
+ DBG1(DBG_CFG, "RADIUS Message-Authenticator invalid length");
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ memcpy(buf, data.ptr, data.len);
+ memset(data.ptr, 0, data.len);
+ if (signer->verify_signature(signer, msg,
+ chunk_create(buf, sizeof(buf))))
+ {
+ /* restore Message-Authenticator */
+ memcpy(data.ptr, buf, data.len);
+ has_auth = TRUE;
+ break;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "RADIUS Message-Authenticator verification failed");
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ else if (type == RAT_EAP_MESSAGE)
+ {
+ has_eap = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ /* restore Response-Authenticator */
+ memcpy(this->msg->authenticator, res_auth, HASH_SIZE_MD5);
+
+ if (has_eap && !has_auth)
+ { /* Message-Authenticator is required if we have an EAP-Message */
+ DBG1(DBG_CFG, "RADIUS Message-Authenticator attribute missing");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of radius_message_t.get_code
+ */
+static radius_message_code_t get_code(private_radius_message_t *this)
+{
+ return this->msg->code;
+}
+
+/**
+ * Implementation of radius_message_t.get_identifier
+ */
+static u_int8_t get_identifier(private_radius_message_t *this)
+{
+ return this->msg->identifier;
+}
+
+/**
+ * Implementation of radius_message_t.set_identifier
+ */
+static void set_identifier(private_radius_message_t *this, u_int8_t identifier)
+{
+ this->msg->identifier = identifier;
+}
+
+/**
+ * Implementation of radius_message_t.get_authenticator
+ */
+static u_int8_t* get_authenticator(private_radius_message_t *this)
+{
+ return this->msg->authenticator;
+}
+
+
+/**
+ * Implementation of radius_message_t.get_encoding
+ */
+static chunk_t get_encoding(private_radius_message_t *this)
+{
+ return chunk_create((u_char*)this->msg, ntohs(this->msg->length));
+}
+
+/**
+ * Implementation of radius_message_t.destroy.
+ */
+static void destroy(private_radius_message_t *this)
+{
+ free(this->msg);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_radius_message_t *radius_message_create()
+{
+ private_radius_message_t *this = malloc_thing(private_radius_message_t);
+
+ this->public.create_enumerator = (enumerator_t*(*)(radius_message_t*))create_enumerator;
+ this->public.add = (void(*)(radius_message_t*, radius_attribute_type_t,chunk_t))add;
+ this->public.get_code = (radius_message_code_t(*)(radius_message_t*))get_code;
+ this->public.get_identifier = (u_int8_t(*)(radius_message_t*))get_identifier;
+ this->public.set_identifier = (void(*)(radius_message_t*, u_int8_t identifier))set_identifier;
+ this->public.get_authenticator = (u_int8_t*(*)(radius_message_t*))get_authenticator;
+ this->public.get_encoding = (chunk_t(*)(radius_message_t*))get_encoding;
+ this->public.sign = (void(*)(radius_message_t*, rng_t *rng, signer_t *signer))sign;
+ this->public.verify = (bool(*)(radius_message_t*, u_int8_t *req_auth, chunk_t secret, hasher_t *hasher, signer_t *signer))verify;
+ this->public.destroy = (void(*)(radius_message_t*))destroy;
+
+ return this;
+}
+
+/**
+ * See header
+ */
+radius_message_t *radius_message_create_request()
+{
+ private_radius_message_t *this = radius_message_create();
+
+ this->msg = malloc_thing(rmsg_t);
+ this->msg->code = RMC_ACCESS_REQUEST;
+ this->msg->identifier = 0;
+ this->msg->length = htons(sizeof(rmsg_t));
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+radius_message_t *radius_message_parse_response(chunk_t data)
+{
+ private_radius_message_t *this = radius_message_create();
+
+ this->msg = malloc(data.len);
+ memcpy(this->msg, data.ptr, data.len);
+ if (data.len < sizeof(rmsg_t) ||
+ ntohs(this->msg->length) != data.len)
+ {
+ DBG1(DBG_IKE, "RADIUS message has invalid length");
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_radius/radius_message.h b/src/libcharon/plugins/eap_radius/radius_message.h
new file mode 100644
index 000000000..266839d3b
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_message.h
@@ -0,0 +1,276 @@
+/*
+ * 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 radius_message radius_message
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef RADIUS_MESSAGE_H_
+#define RADIUS_MESSAGE_H_
+
+#include <library.h>
+
+typedef struct radius_message_t radius_message_t;
+typedef enum radius_message_code_t radius_message_code_t;
+typedef enum radius_attribute_type_t radius_attribute_type_t;
+
+/**
+ * RADIUS Message Codes.
+ */
+enum radius_message_code_t {
+ RMC_ACCESS_REQUEST = 1,
+ RMC_ACCESS_ACCEPT = 2,
+ RMC_ACCESS_REJECT = 3,
+ RMC_ACCOUNTING_REQUEST = 4,
+ RMC_ACCOUNTING_RESPONSE = 5,
+ RMC_ACCESS_CHALLENGE = 11,
+};
+
+/**
+ * Enum names for radius_attribute_type_t.
+ */
+extern enum_name_t *radius_message_code_names;
+
+/**
+ * RADIUS Attribute Types.
+ */
+enum radius_attribute_type_t {
+ RAT_USER_NAME = 1,
+ RAT_USER_PASSWORD = 2,
+ RAT_CHAP_PASSWORD = 3,
+ RAT_NAS_IP_ADDRESS = 4,
+ RAT_NAS_PORT = 5,
+ RAT_SERVICE_TYPE = 6,
+ RAT_FRAMED_PROTOCOL = 7,
+ RAT_FRAMED_IP_ADDRESS = 8,
+ RAT_FRAMED_IP_NETMASK = 9,
+ RAT_FRAMED_ROUTING = 10,
+ RAT_FILTER_ID = 11,
+ RAT_FRAMED_MTU = 12,
+ RAT_FRAMED_COMPRESSION = 13,
+ RAT_LOGIN_IP_HOST = 14,
+ RAT_LOGIN_SERVICE = 15,
+ RAT_LOGIN_TCP_PORT = 16,
+ RAT_REPLY_MESSAGE = 18,
+ RAT_CALLBACK_NUMBER = 19,
+ RAT_CALLBACK_ID = 20,
+ RAT_FRAMED_ROUTE = 22,
+ RAT_FRAMED_IPX_NETWORK = 23,
+ RAT_STATE = 24,
+ RAT_CLASS = 25,
+ RAT_VENDOR_SPECIFIC = 26,
+ RAT_SESSION_TIMEOUT = 27,
+ RAT_IDLE_TIMEOUT = 28,
+ RAT_TERMINATION_ACTION = 29,
+ RAT_CALLED_STATION_ID = 30,
+ RAT_CALLING_STATION_ID = 31,
+ RAT_NAS_IDENTIFIER = 32,
+ RAT_PROXY_STATE = 33,
+ RAT_LOGIN_LAT_SERVICE = 34,
+ RAT_LOGIN_LAT_NODE = 35,
+ RAT_LOGIN_LAT_GROUP = 36,
+ RAT_FRAMED_APPLETALK_LINK = 37,
+ RAT_FRAMED_APPLETALK_NETWORK = 38,
+ RAT_FRAMED_APPLETALK_ZONE = 39,
+ RAT_ACCT_STATUS_TYPE = 40,
+ RAT_ACCT_DELAY_TIME = 41,
+ RAT_ACCT_INPUT_OCTETS = 42,
+ RAT_ACCT_OUTPUT_OCTETS = 43,
+ RAT_ACCT_SESSION_ID = 44,
+ RAT_ACCT_AUTHENTIC = 45,
+ RAT_ACCT_SESSION_TIME = 46,
+ RAT_ACCT_INPUT_PACKETS = 47,
+ RAT_ACCT_OUTPUT_PACKETS = 48,
+ RAT_ACCT_TERMINATE_CAUSE = 49,
+ RAT_ACCT_MULTI_SESSION_ID = 50,
+ RAT_ACCT_LINK_COUNT = 51,
+ RAT_ACCT_INPUT_GIGAWORDS = 52,
+ RAT_ACCT_OUTPUT_GIGAWORDS = 53,
+ RAT_EVENT_TIMESTAMP = 55,
+ RAT_EGRESS_VLANID = 56,
+ RAT_INGRESS_FILTERS = 57,
+ RAT_EGRESS_VLAN_NAME = 58,
+ RAT_USER_PRIORITY_TABLE = 59,
+ RAT_CHAP_CHALLENGE = 60,
+ RAT_NAS_PORT_TYPE = 61,
+ RAT_PORT_LIMIT = 62,
+ RAT_LOGIN_LAT_PORT = 63,
+ RAT_TUNNEL_TYPE = 64,
+ RAT_TUNNEL_MEDIUM_TYPE = 65,
+ RAT_TUNNEL_CLIENT_ENDPOINT = 66,
+ RAT_TUNNEL_SERVER_ENDPOINT = 67,
+ RAT_ACCT_TUNNEL_CONNECTION = 68,
+ RAT_TUNNEL_PASSWORD = 69,
+ RAT_ARAP_PASSWORD = 70,
+ RAT_ARAP_FEATURES = 71,
+ RAT_ARAP_ZONE_ACCESS = 72,
+ RAT_ARAP_SECURITY = 73,
+ RAT_ARAP_SECURITY_DATA = 74,
+ RAT_PASSWORD_RETRY = 75,
+ RAT_PROMPT = 76,
+ RAT_CONNECT_INFO = 77,
+ RAT_CONFIGURATION_TOKEN = 78,
+ RAT_EAP_MESSAGE = 79,
+ RAT_MESSAGE_AUTHENTICATOR = 80,
+ RAT_TUNNEL_PRIVATE_GROUP_ID = 81,
+ RAT_TUNNEL_ASSIGNMENT_ID = 82,
+ RAT_TUNNEL_PREFERENCE = 83,
+ RAT_ARAP_CHALLENGE_RESPONSE = 84,
+ RAT_ACCT_INTERIM_INTERVAL = 85,
+ RAT_ACCT_TUNNEL_PACKETS_LOST = 86,
+ RAT_NAS_PORT_ID = 87,
+ RAT_FRAMED_POOL = 88,
+ RAT_CUI = 89,
+ RAT_TUNNEL_CLIENT_AUTH_ID = 90,
+ RAT_TUNNEL_SERVER_AUTH_ID = 91,
+ RAT_NAS_FILTER_RULE = 92,
+ RAT_UNASSIGNED = 93,
+ RAT_ORIGINATING_LINE_INFO = 94,
+ RAT_NAS_IPV6_ADDRESS = 95,
+ RAT_FRAMED_INTERFACE_ID = 96,
+ RAT_FRAMED_IPV6_PREFIX = 97,
+ RAT_LOGIN_IPV6_HOST = 98,
+ RAT_FRAMED_IPV6_ROUTE = 99,
+ RAT_FRAMED_IPV6_POOL = 100,
+ RAT_ERROR_CAUSE = 101,
+ RAT_EAP_KEY_NAME = 102,
+ RAT_DIGEST_RESPONSE = 103,
+ RAT_DIGEST_REALM = 104,
+ RAT_DIGEST_NONCE = 105,
+ RAT_DIGEST_RESPONSE_AUTH = 106,
+ RAT_DIGEST_NEXTNONCE = 107,
+ RAT_DIGEST_METHOD = 108,
+ RAT_DIGEST_URI = 109,
+ RAT_DIGEST_QOP = 110,
+ RAT_DIGEST_ALGORITHM = 111,
+ RAT_DIGEST_ENTITY_BODY_HASH = 112,
+ RAT_DIGEST_CNONCE = 113,
+ RAT_DIGEST_NONCE_COUNT = 114,
+ RAT_DIGEST_USERNAME = 115,
+ RAT_DIGEST_OPAQUE = 116,
+ RAT_DIGEST_AUTH_PARAM = 117,
+ RAT_DIGEST_AKA_AUTS = 118,
+ RAT_DIGEST_DOMAIN = 119,
+ RAT_DIGEST_STALE = 120,
+ RAT_DIGEST_HA1 = 121,
+ RAT_SIP_AOR = 122,
+ RAT_DELEGATED_IPV6_PREFIX = 123,
+ RAT_MIP6_FEATURE_VECTOR = 124,
+ RAT_MIP6_HOME_LINK_PREFIX = 125,
+};
+
+/**
+ * Enum names for radius_attribute_type_t.
+ */
+extern enum_name_t *radius_attribute_type_names;
+
+/**
+ * A RADIUS message, contains attributes.
+ */
+struct radius_message_t {
+
+ /**
+ * Create an enumerator over contained RADIUS attributes.
+ *
+ * @return enumerator over (int type, chunk_t data)
+ */
+ enumerator_t* (*create_enumerator)(radius_message_t *this);
+
+ /**
+ * Add a RADIUS attribute to the message.
+ *
+ * @param type type of attribute to add
+ * @param attribute data, gets cloned
+ */
+ void (*add)(radius_message_t *this, radius_attribute_type_t type,
+ chunk_t data);
+
+ /**
+ * Get the message type (code).
+ *
+ * @return message code
+ */
+ radius_message_code_t (*get_code)(radius_message_t *this);
+
+ /**
+ * Get the message identifier.
+ *
+ * @return message identifier
+ */
+ u_int8_t (*get_identifier)(radius_message_t *this);
+
+ /**
+ * Set the message identifier.
+ *
+ * @param identifier message identifier
+ */
+ void (*set_identifier)(radius_message_t *this, u_int8_t identifier);
+
+ /**
+ * Get the 16 byte authenticator.
+ *
+ * @return pointer to the Authenticator field
+ */
+ u_int8_t* (*get_authenticator)(radius_message_t *this);
+
+ /**
+ * Get the RADIUS message in its encoded form.
+ *
+ * @return chunk pointing to internal RADIUS message.
+ */
+ chunk_t (*get_encoding)(radius_message_t *this);
+
+ /**
+ * Calculate and add the Message-Authenticator attribute to the message.
+ *
+ * @param rng RNG to create Request-Authenticator
+ * @param signer HMAC-MD5 signer with secret set
+ */
+ void (*sign)(radius_message_t *this, rng_t *rng, signer_t *signer);
+
+ /**
+ * Verify the integrity of a received RADIUS response.
+ *
+ * @param req_auth 16 byte Authenticator of the corresponding request
+ * @param secret shared RADIUS secret
+ * @param hasher hasher to verify Response-Authenticator
+ * @param signer signer to verify Message-Authenticator attribute
+ */
+ bool (*verify)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
+ hasher_t *hasher, signer_t *signer);
+
+ /**
+ * Destroy the message.
+ */
+ void (*destroy)(radius_message_t *this);
+};
+
+/**
+ * Create an empty RADIUS request message (RMT_ACCESS_REQUEST).
+ *
+ * @return radius_message_t object
+ */
+radius_message_t *radius_message_create_request();
+
+/**
+ * Parse and verify a recevied RADIUS response.
+ *
+ * @param data received message data
+ * @return radius_message_t object, NULL if length invalid
+ */
+radius_message_t *radius_message_parse_response(chunk_t data);
+
+#endif /** RADIUS_MESSAGE_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim/Makefile.am b/src/libcharon/plugins/eap_sim/Makefile.am
new file mode 100644
index 000000000..a0cb72f5f
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-sim.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-sim.la
+libstrongswan_eap_sim_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la
+endif
+
+libstrongswan_eap_sim_la_SOURCES = \
+ eap_sim_plugin.h eap_sim_plugin.c \
+ eap_sim_peer.h eap_sim_peer.c \
+ eap_sim_server.h eap_sim_server.c
+
+libstrongswan_eap_sim_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
new file mode 100644
index 000000000..588965113
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -0,0 +1,593 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_sim
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_eap_sim_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la
+am_libstrongswan_eap_sim_la_OBJECTS = eap_sim_plugin.lo \
+ eap_sim_peer.lo eap_sim_server.lo
+libstrongswan_eap_sim_la_OBJECTS = \
+ $(am_libstrongswan_eap_sim_la_OBJECTS)
+libstrongswan_eap_sim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_sim_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_sim_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_sim_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim.la
+@MONOLITHIC_FALSE@libstrongswan_eap_sim_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la
+libstrongswan_eap_sim_la_SOURCES = \
+ eap_sim_plugin.h eap_sim_plugin.c \
+ eap_sim_peer.h eap_sim_peer.c \
+ eap_sim_server.h eap_sim_server.c
+
+libstrongswan_eap_sim_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-sim.la: $(libstrongswan_eap_sim_la_OBJECTS) $(libstrongswan_eap_sim_la_DEPENDENCIES)
+ $(libstrongswan_eap_sim_la_LINK) $(am_libstrongswan_eap_sim_la_rpath) $(libstrongswan_eap_sim_la_OBJECTS) $(libstrongswan_eap_sim_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_peer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_server.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
new file mode 100644
index 000000000..961cfd30d
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) 2007-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 "eap_sim_peer.h"
+
+#include <daemon.h>
+
+#include <simaka_message.h>
+
+/* number of tries we do authenticate */
+#define MAX_TRIES 3
+
+/* number of triplets for one authentication */
+#define TRIPLET_COUNT 3
+
+/** length of the AT_NONCE_MT nonce value */
+#define NONCE_LEN 16
+
+typedef struct private_eap_sim_peer_t private_eap_sim_peer_t;
+
+/**
+ * Private data of an eap_sim_peer_t object.
+ */
+struct private_eap_sim_peer_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_sim_peer_t public;
+
+ /**
+ * permanent ID of peer
+ */
+ identification_t *permanent;
+
+ /**
+ * Pseudonym identity the peer uses
+ */
+ identification_t *pseudonym;
+
+ /**
+ * Reauthentication identity the peer uses
+ */
+ identification_t *reauth;
+
+ /**
+ * EAP-SIM crypto helper
+ */
+ simaka_crypto_t *crypto;
+
+ /**
+ * how many times we try to authenticate
+ */
+ int tries;
+
+ /**
+ * version list received from server
+ */
+ chunk_t version_list;
+
+ /**
+ * Nonce value used in AT_NONCE_MT/AT_NONCE_S
+ */
+ chunk_t nonce;
+
+ /**
+ * MSK, used for EAP-SIM based IKEv2 authentication
+ */
+ chunk_t msk;
+
+ /**
+ * Master key, if reauthentication is used
+ */
+ char mk[HASH_SIZE_SHA1];
+
+ /**
+ * Counter value if reauthentication is used
+ */
+ u_int16_t counter;
+};
+
+/* version of SIM protocol we speak */
+static chunk_t version = chunk_from_chars(0x00,0x01);
+
+/**
+ * Create a SIM_CLIENT_ERROR
+ */
+static eap_payload_t* create_client_error(private_eap_sim_peer_t *this,
+ u_int8_t identifier, simaka_client_error_t code)
+{
+ simaka_message_t *message;
+ eap_payload_t *out;
+ u_int16_t encoded;
+
+ DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code);
+
+ message = simaka_message_create(FALSE, identifier, EAP_SIM,
+ SIM_CLIENT_ERROR, this->crypto);
+ encoded = htons(code);
+ message->add_attribute(message, AT_CLIENT_ERROR_CODE,
+ chunk_create((char*)&encoded, sizeof(encoded)));
+ out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ return out;
+}
+
+/**
+ * process an EAP-SIM/Request/Start message
+ */
+static status_t process_start(private_eap_sim_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, id = chunk_empty;
+ rng_t *rng;
+ bool supported = FALSE;
+ simaka_attribute_t id_req = 0;
+
+ /* reset previously uses reauthentication/pseudonym data */
+ this->crypto->clear_keys(this->crypto);
+ DESTROY_IF(this->pseudonym);
+ this->pseudonym = NULL;
+ DESTROY_IF(this->reauth);
+ this->reauth = NULL;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_VERSION_LIST:
+ {
+ free(this->version_list.ptr);
+ this->version_list = chunk_clone(data);
+ while (data.len >= version.len)
+ {
+ if (memeq(data.ptr, version.ptr, version.len))
+ {
+ supported = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ case AT_ANY_ID_REQ:
+ case AT_FULLAUTH_ID_REQ:
+ case AT_PERMANENT_ID_REQ:
+ id_req = type;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!supported)
+ {
+ DBG1(DBG_IKE, "server does not support EAP-SIM version number 1");
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNSUPPORTED_VERSION);
+ return NEED_MORE;
+ }
+
+ switch (id_req)
+ {
+ case AT_ANY_ID_REQ:
+ this->reauth = charon->sim->card_get_reauth(charon->sim,
+ this->permanent, this->mk, &this->counter);
+ if (this->reauth)
+ {
+ id = this->reauth->get_encoding(this->reauth);
+ break;
+ }
+ /* FALL */
+ case AT_FULLAUTH_ID_REQ:
+ this->pseudonym = charon->sim->card_get_pseudonym(charon->sim,
+ this->permanent);
+ if (this->pseudonym)
+ {
+ id = this->pseudonym->get_encoding(this->pseudonym);
+ break;
+ }
+ /* FALL */
+ case AT_PERMANENT_ID_REQ:
+ id = this->permanent->get_encoding(this->permanent);
+ break;
+ default:
+ break;
+ }
+
+ /* generate AT_NONCE_MT value */
+ rng = this->crypto->get_rng(this->crypto);
+ free(this->nonce.ptr);
+ rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM,
+ SIM_START, this->crypto);
+ if (!this->reauth)
+ {
+ message->add_attribute(message, AT_SELECTED_VERSION, version);
+ message->add_attribute(message, AT_NONCE_MT, this->nonce);
+ }
+ if (id.len)
+ {
+ message->add_attribute(message, AT_IDENTITY, id);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ return NEED_MORE;
+}
+
+/**
+ * process an EAP-SIM/Request/Challenge message
+ */
+static status_t process_challenge(private_eap_sim_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, rands = chunk_empty, kcs, kc, sreses, sres, mk;
+ identification_t *id;
+
+ if (this->tries-- <= 0)
+ {
+ /* give up without notification. This hack is required as some buggy
+ * server implementations won't respect our client-error. */
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_RAND:
+ rands = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* excepting two or three RAND, each 16 bytes. We require two valid
+ * and different RANDs */
+ if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
+ memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
+ {
+ DBG1(DBG_IKE, "no valid AT_RAND received");
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_INSUFFICIENT_CHALLENGES);
+ return NEED_MORE;
+ }
+ /* get two or three KCs/SRESes from SIM using RANDs */
+ kcs = kc = chunk_alloca(rands.len / 2);
+ sreses = sres = chunk_alloca(rands.len / 4);
+ while (rands.len >= SIM_RAND_LEN)
+ {
+ if (!charon->sim->card_get_triplet(charon->sim, this->permanent,
+ rands.ptr, sres.ptr, kc.ptr))
+ {
+ DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+ DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b",
+ rands.ptr, SIM_RAND_LEN, sres.ptr, SIM_SRES_LEN, kc.ptr, SIM_KC_LEN);
+ kc = chunk_skip(kc, SIM_KC_LEN);
+ sres = chunk_skip(sres, SIM_SRES_LEN);
+ rands = chunk_skip(rands, SIM_RAND_LEN);
+ }
+
+ id = this->permanent;
+ if (this->pseudonym)
+ {
+ id = this->pseudonym;
+ }
+ data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version);
+ free(this->msk.ptr);
+ this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ memcpy(this->mk, mk.ptr, mk.len);
+ free(mk.ptr);
+
+ /* Verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT", and
+ * parse() again after key derivation, reading encrypted attributes */
+ if (!in->verify(in, this->nonce) || !in->parse(in))
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_NEXT_REAUTH_ID:
+ this->counter = 0;
+ id = identification_create_from_data(data);
+ charon->sim->card_set_reauth(charon->sim, this->permanent, id,
+ this->mk, this->counter);
+ id->destroy(id);
+ break;
+ case AT_NEXT_PSEUDONYM:
+ id = identification_create_from_data(data);
+ charon->sim->card_set_pseudonym(charon->sim, this->permanent, id);
+ id->destroy(id);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* build response with AT_MAC, built over "EAP packet | n*SRES" */
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM,
+ SIM_CHALLENGE, this->crypto);
+ *out = message->generate(message, sreses);
+ message->destroy(message);
+ return NEED_MORE;
+}
+
+/**
+ * Check if a received counter value is acceptable
+ */
+static bool counter_too_small(private_eap_sim_peer_t *this, chunk_t chunk)
+{
+ u_int16_t counter;
+
+ memcpy(&counter, chunk.ptr, sizeof(counter));
+ counter = htons(counter);
+ return counter < this->counter;
+}
+
+/**
+ * process an EAP-SIM/Request/Re-Authentication message
+ */
+static status_t process_reauthentication(private_eap_sim_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, counter = chunk_empty, nonce = chunk_empty, id = chunk_empty;
+
+ if (!this->reauth)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, SIM_REAUTHENTICATION);
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+
+ this->crypto->derive_keys_reauth(this->crypto,
+ chunk_create(this->mk, HASH_SIZE_SHA1));
+
+ /* verify MAC and parse again with decryption key */
+ if (!in->verify(in, chunk_empty) || !in->parse(in))
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_COUNTER:
+ counter = data;
+ break;
+ case AT_NONCE_S:
+ nonce = data;
+ break;
+ case AT_NEXT_REAUTH_ID:
+ id = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!nonce.len || !counter.len)
+ {
+ DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete");
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM,
+ SIM_REAUTHENTICATION, this->crypto);
+ if (counter_too_small(this, counter))
+ {
+ DBG1(DBG_IKE, "reauthentication counter too small");
+ message->add_attribute(message, AT_COUNTER_TOO_SMALL, chunk_empty);
+ }
+ else
+ {
+ free(this->msk.ptr);
+ this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, counter, nonce,
+ chunk_create(this->mk, HASH_SIZE_SHA1));
+ if (id.len)
+ {
+ identification_t *reauth;
+
+ reauth = identification_create_from_data(data);
+ charon->sim->card_set_reauth(charon->sim, this->permanent, reauth,
+ this->mk, this->counter);
+ reauth->destroy(reauth);
+ }
+ }
+ message->add_attribute(message, AT_COUNTER, counter);
+ *out = message->generate(message, nonce);
+ message->destroy(message);
+ return NEED_MORE;
+}
+
+/**
+ * process an EAP-SIM/Request/Notification message
+ */
+static status_t process_notification(private_eap_sim_peer_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data;
+ bool success = TRUE;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == AT_NOTIFICATION)
+ {
+ u_int16_t code;
+
+ memcpy(&code, data.ptr, sizeof(code));
+ code = ntohs(code);
+
+ /* test success bit */
+ if (!(data.ptr[0] & 0x80))
+ {
+ success = FALSE;
+ DBG1(DBG_IKE, "received EAP-SIM notification error '%N'",
+ simaka_notification_names, code);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received EAP-SIM notification '%N'",
+ simaka_notification_names, code);
+ }
+ }
+ else if (!simaka_attribute_skippable(type))
+ {
+ success = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (success)
+ { /* empty notification reply */
+ message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM,
+ SIM_NOTIFICATION, this->crypto);
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+ }
+ else
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of eap_method_t.process
+ */
+static status_t process(private_eap_sim_peer_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ status_t status;
+
+ message = simaka_message_create_from_payload(in, this->crypto);
+ if (!message)
+ {
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+ if (!message->parse(message))
+ {
+ message->destroy(message);
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ return NEED_MORE;
+ }
+ switch (message->get_subtype(message))
+ {
+ case SIM_START:
+ status = process_start(this, message, out);
+ break;
+ case SIM_CHALLENGE:
+ status = process_challenge(this, message, out);
+ break;
+ case SIM_REAUTHENTICATION:
+ status = process_reauthentication(this, message, out);
+ break;
+ case SIM_NOTIFICATION:
+ status = process_notification(this, message, out);
+ break;
+ default:
+ DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
+ simaka_subtype_names, message->get_subtype(message));
+ *out = create_client_error(this, in->get_identifier(in),
+ SIM_UNABLE_TO_PROCESS);
+ status = NEED_MORE;
+ break;
+ }
+ message->destroy(message);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.initiate
+ */
+static status_t initiate(private_eap_sim_peer_t *this, eap_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_sim_peer_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_SIM;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_sim_peer_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_sim_peer_t *this)
+{
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_sim_peer_t *this)
+{
+ this->permanent->destroy(this->permanent);
+ DESTROY_IF(this->pseudonym);
+ DESTROY_IF(this->reauth);
+ this->crypto->destroy(this->crypto);
+ free(this->version_list.ptr);
+ free(this->nonce.ptr);
+ free(this->msk.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_sim_peer_t *this = malloc_thing(private_eap_sim_peer_t);
+
+ this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
+ this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->crypto = simaka_crypto_create();
+ if (!this->crypto)
+ {
+ free(this);
+ return NULL;
+ }
+ this->permanent = peer->clone(peer);
+ this->pseudonym = NULL;
+ this->reauth = NULL;
+ this->tries = MAX_TRIES;
+ this->version_list = chunk_empty;
+ this->nonce = chunk_empty;
+ this->msk = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.h b/src/libcharon/plugins/eap_sim/eap_sim_peer.h
new file mode 100644
index 000000000..89f81301e
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.h
@@ -0,0 +1,57 @@
+/*
+ * 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 eap_sim_peer eap_sim_peer
+ * @{ @ingroup eap_sim
+ */
+
+#ifndef EAP_SIM_PEER_H_
+#define EAP_SIM_PEER_H_
+
+#include <sa/authenticators/eap/eap_method.h>
+
+typedef struct eap_sim_peer_t eap_sim_peer_t;
+
+/**
+ * EAP-SIM peer implementation.
+ *
+ * This EAP-SIM module uses sim_card_t implementations for triplet calculation,
+ * found via the eap_sim_manager_t.
+ */
+struct eap_sim_peer_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t interface;
+
+ /**
+ * Destroy a eap_sim_peer_t.
+ */
+ void (*destroy)(eap_sim_peer_t *this);
+};
+
+/**
+ * Creates the EAP method EAP-SIM acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP peer
+ * @return eap_sim_t object
+ */
+eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_SIM_PEER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_plugin.c b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c
new file mode 100644
index 000000000..f0c972253
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008-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 "eap_sim_plugin.h"
+
+#include "eap_sim_server.h"
+#include "eap_sim_peer.h"
+
+#include <daemon.h>
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(eap_sim_plugin_t *this)
+{
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_sim_server_create);
+ charon->eap->remove_method(charon->eap,
+ (eap_constructor_t)eap_sim_peer_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_sim_plugin_create()
+{
+ eap_sim_plugin_t *this = malloc_thing(eap_sim_plugin_t);
+
+ this->plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER,
+ (eap_constructor_t)eap_sim_server_create);
+ charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_PEER,
+ (eap_constructor_t)eap_sim_peer_create);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_plugin.h b/src/libcharon/plugins/eap_sim/eap_sim_plugin.h
new file mode 100644
index 000000000..4e10380c4
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_sim eap_sim
+ * @ingroup cplugins
+ *
+ * @defgroup eap_sim_plugin eap_sim_plugin
+ * @{ @ingroup eap_sim
+ */
+
+#ifndef EAP_SIM_PLUGIN_H_
+#define EAP_SIM_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_sim_plugin_t eap_sim_plugin_t;
+
+/**
+ * EAP-SIM plugin.
+ */
+struct eap_sim_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_SIM_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c
new file mode 100644
index 000000000..f6d5df09b
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2007-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 "eap_sim_server.h"
+
+#include <daemon.h>
+
+#include <simaka_message.h>
+#include <simaka_crypto.h>
+
+/* number of triplets for one authentication */
+#define TRIPLET_COUNT 3
+
+/** length of the AT_NONCE_S value */
+#define NONCE_LEN 16
+
+typedef struct private_eap_sim_server_t private_eap_sim_server_t;
+
+/**
+ * Private data of an eap_sim_server_t object.
+ */
+struct private_eap_sim_server_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_sim_server_t public;
+
+ /**
+ * permanent ID of peer
+ */
+ identification_t *permanent;
+
+ /**
+ * pseudonym ID of peer
+ */
+ identification_t *pseudonym;
+
+ /**
+ * reauthentication ID of peer
+ */
+ identification_t *reauth;
+
+ /**
+ * EAP-SIM/AKA crypto helper
+ */
+ simaka_crypto_t *crypto;
+
+ /**
+ * unique EAP identifier
+ */
+ u_int8_t identifier;
+
+ /**
+ * concatenated SRES values
+ */
+ chunk_t sreses;
+
+ /**
+ * Nonce value used in AT_NONCE_S
+ */
+ chunk_t nonce;
+
+ /**
+ * Counter value negotiated, network order
+ */
+ chunk_t counter;
+
+ /**
+ * MSK, used for EAP-SIM based IKEv2 authentication
+ */
+ chunk_t msk;
+
+ /**
+ * Do we request fast reauthentication?
+ */
+ bool use_reauth;
+
+ /**
+ * Do we request pseudonym identities?
+ */
+ bool use_pseudonym;
+
+ /**
+ * Do we request permanent identities?
+ */
+ bool use_permanent;
+
+ /**
+ * EAP-SIM message we have initiated
+ */
+ simaka_subtype_t pending;
+};
+
+/* version of SIM protocol we speak */
+static chunk_t version = chunk_from_chars(0x00,0x01);
+
+/**
+ * Implementation of eap_method_t.initiate
+ */
+static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out)
+{
+ simaka_message_t *message;
+
+ message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
+ SIM_START, this->crypto);
+ message->add_attribute(message, AT_VERSION_LIST, version);
+ if (this->use_reauth)
+ {
+ message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty);
+ }
+ else if (this->use_pseudonym)
+ {
+ message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty);
+ }
+ else if (this->use_permanent)
+ {
+ message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ this->pending = SIM_START;
+ return NEED_MORE;
+}
+
+/**
+ * Initiate EAP-SIM/Request/Re-authentication message
+ */
+static status_t reauthenticate(private_eap_sim_server_t *this,
+ char mk[HASH_SIZE_SHA1], u_int16_t counter,
+ eap_payload_t **out)
+{
+ simaka_message_t *message;
+ identification_t *next;
+ chunk_t mkc;
+ rng_t *rng;
+
+ DBG1(DBG_IKE, "initiating EAP-SIM reauthentication");
+
+ rng = this->crypto->get_rng(this->crypto);
+ rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+
+ mkc = chunk_create(mk, HASH_SIZE_SHA1);
+ counter = htons(counter);
+ this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
+
+ this->crypto->derive_keys_reauth(this->crypto, mkc);
+ this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, this->counter, this->nonce, mkc);
+
+ message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
+ SIM_REAUTHENTICATION, this->crypto);
+ message->add_attribute(message, AT_COUNTER, this->counter);
+ message->add_attribute(message, AT_NONCE_S, this->nonce);
+ next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk);
+ if (next)
+ {
+ message->add_attribute(message, AT_NEXT_REAUTH_ID,
+ next->get_encoding(next));
+ next->destroy(next);
+ }
+ *out = message->generate(message, chunk_empty);
+ message->destroy(message);
+
+ this->pending = SIM_REAUTHENTICATION;
+ return NEED_MORE;
+}
+
+/**
+ * process an EAP-SIM/Response/Reauthentication message
+ */
+static status_t process_reauthentication(private_eap_sim_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, counter = chunk_empty;
+ bool too_small = FALSE;
+
+ if (this->pending != SIM_REAUTHENTICATION)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, SIM_REAUTHENTICATION);
+ return FAILED;
+ }
+ /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_S" */
+ if (!in->verify(in, this->nonce))
+ {
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_COUNTER:
+ counter = data;
+ break;
+ case AT_COUNTER_TOO_SMALL:
+ too_small = TRUE;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (too_small)
+ {
+ DBG1(DBG_IKE, "received %N, initiating full authentication",
+ simaka_attribute_names, AT_COUNTER_TOO_SMALL);
+ this->use_reauth = FALSE;
+ this->crypto->clear_keys(this->crypto);
+ return initiate(this, out);
+ }
+ if (!chunk_equals(counter, this->counter))
+ {
+ DBG1(DBG_IKE, "received counter does not match");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * process an EAP-SIM/Response/Start message
+ */
+static status_t process_start(private_eap_sim_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data, identity = chunk_empty, nonce = chunk_empty, mk;
+ chunk_t rands, rand, kcs, kc, sreses, sres;
+ bool supported = FALSE;
+ identification_t *id;
+ int i;
+
+ if (this->pending != SIM_START)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, SIM_START);
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ switch (type)
+ {
+ case AT_NONCE_MT:
+ nonce = data;
+ break;
+ case AT_SELECTED_VERSION:
+ if (chunk_equals(data, version))
+ {
+ supported = TRUE;
+ }
+ break;
+ case AT_IDENTITY:
+ identity = data;
+ break;
+ default:
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (identity.len)
+ {
+ identification_t *permanent;
+
+ id = identification_create_from_data(identity);
+ if (this->use_reauth && !nonce.len)
+ {
+ char mk[HASH_SIZE_SHA1];
+ u_int16_t counter;
+
+ permanent = charon->sim->provider_is_reauth(charon->sim, id,
+ mk, &counter);
+ if (permanent)
+ {
+ this->permanent->destroy(this->permanent);
+ this->permanent = permanent;
+ this->reauth = id;
+ return reauthenticate(this, mk, counter, out);
+ }
+ DBG1(DBG_IKE, "received unknown reauthentication identity '%Y', "
+ "initiating full authentication", id);
+ this->use_reauth = FALSE;
+ id->destroy(id);
+ return initiate(this, out);
+ }
+ if (this->use_pseudonym)
+ {
+ permanent = charon->sim->provider_is_pseudonym(charon->sim, id);
+ if (permanent)
+ {
+ this->permanent->destroy(this->permanent);
+ this->permanent = permanent;
+ this->pseudonym = id->clone(id);
+ /* we already have a new permanent identity now */
+ this->use_permanent = FALSE;
+ }
+ }
+ if (!this->pseudonym && this->use_permanent)
+ {
+ DBG1(DBG_IKE, "received %spermanent identity '%Y'",
+ this->use_pseudonym ? "pseudonym or " : "", id);
+ this->permanent->destroy(this->permanent);
+ this->permanent = id->clone(id);
+ }
+ id->destroy(id);
+ }
+
+ if (!supported || !nonce.len)
+ {
+ DBG1(DBG_IKE, "received incomplete EAP-SIM/Response/Start");
+ return FAILED;
+ }
+
+ /* read triplets from provider */
+ rand = rands = chunk_alloca(SIM_RAND_LEN * TRIPLET_COUNT);
+ kc = kcs = chunk_alloca(SIM_KC_LEN * TRIPLET_COUNT);
+ sres = sreses = chunk_alloca(SIM_SRES_LEN * TRIPLET_COUNT);
+ rands.len = kcs.len = sreses.len = 0;
+ for (i = 0; i < TRIPLET_COUNT; i++)
+ {
+ if (!charon->sim->provider_get_triplet(charon->sim, this->permanent,
+ rand.ptr, sres.ptr, kc.ptr))
+ {
+ if (this->use_pseudonym)
+ {
+ /* probably received a pseudonym we couldn't map */
+ DBG1(DBG_IKE, "failed to map pseudonym identity '%Y', "
+ "fallback to permanent identity request", this->permanent);
+ this->use_pseudonym = FALSE;
+ DESTROY_IF(this->pseudonym);
+ this->pseudonym = NULL;
+ return initiate(this, out);
+ }
+ return FAILED;
+ }
+ rands.len += SIM_RAND_LEN;
+ sreses.len += SIM_SRES_LEN;
+ kcs.len += SIM_KC_LEN;
+ rand = chunk_skip(rand, SIM_RAND_LEN);
+ sres = chunk_skip(sres, SIM_SRES_LEN);
+ kc = chunk_skip(kc, SIM_KC_LEN);
+ }
+ free(this->sreses.ptr);
+ this->sreses = chunk_clone(sreses);
+
+ data = chunk_cata("cccc", kcs, nonce, version, version);
+ free(this->msk.ptr);
+ id = this->permanent;
+ if (this->pseudonym)
+ {
+ id = this->pseudonym;
+ }
+ this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+
+ /* build response with AT_MAC, built over "EAP packet | NONCE_MT" */
+ message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
+ SIM_CHALLENGE, this->crypto);
+ message->add_attribute(message, AT_RAND, rands);
+ id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr);
+ if (id)
+ {
+ message->add_attribute(message, AT_NEXT_REAUTH_ID,
+ id->get_encoding(id));
+ id->destroy(id);
+ }
+ else
+ {
+ id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent);
+ if (id)
+ {
+ message->add_attribute(message, AT_NEXT_PSEUDONYM,
+ id->get_encoding(id));
+ id->destroy(id);
+ }
+ }
+ *out = message->generate(message, nonce);
+ message->destroy(message);
+
+ free(mk.ptr);
+ this->pending = SIM_CHALLENGE;
+ return NEED_MORE;
+}
+
+/**
+ * process an EAP-SIM/Response/Challenge message
+ */
+static status_t process_challenge(private_eap_sim_server_t *this,
+ simaka_message_t *in, eap_payload_t **out)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data;
+
+ if (this->pending != SIM_CHALLENGE)
+ {
+ DBG1(DBG_IKE, "received %N, but not expected",
+ simaka_subtype_names, SIM_CHALLENGE);
+ return FAILED;
+ }
+ /* verify AT_MAC attribute, signature is over "EAP packet | n*SRES" */
+ if (!in->verify(in, this->sreses))
+ {
+ return FAILED;
+ }
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (!simaka_attribute_skippable(type))
+ {
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return SUCCESS;
+}
+
+/**
+ * EAP-SIM/Response/ClientErrorCode message
+ */
+static status_t process_client_error(private_eap_sim_server_t *this,
+ simaka_message_t *in)
+{
+ enumerator_t *enumerator;
+ simaka_attribute_t type;
+ chunk_t data;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == AT_CLIENT_ERROR_CODE)
+ {
+ u_int16_t code;
+
+ memcpy(&code, data.ptr, sizeof(code));
+ DBG1(DBG_IKE, "received EAP-SIM client error '%N'",
+ simaka_client_error_names, ntohs(code));
+ }
+ else if (!simaka_attribute_skippable(type))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.process
+ */
+static status_t process(private_eap_sim_server_t *this,
+ eap_payload_t *in, eap_payload_t **out)
+{
+ simaka_message_t *message;
+ status_t status;
+
+ message = simaka_message_create_from_payload(in, this->crypto);
+ if (!message)
+ {
+ return FAILED;
+ }
+ if (!message->parse(message))
+ {
+ message->destroy(message);
+ return FAILED;
+ }
+ switch (message->get_subtype(message))
+ {
+ case SIM_START:
+ status = process_start(this, message, out);
+ break;
+ case SIM_CHALLENGE:
+ status = process_challenge(this, message, out);
+ break;
+ case SIM_REAUTHENTICATION:
+ status = process_reauthentication(this, message, out);
+ break;
+ case SIM_CLIENT_ERROR:
+ status = process_client_error(this, message);
+ break;
+ default:
+ DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
+ simaka_subtype_names, message->get_subtype(message));
+ status = FAILED;
+ break;
+ }
+ message->destroy(message);
+ return status;
+}
+
+/**
+ * Implementation of eap_method_t.get_type.
+ */
+static eap_type_t get_type(private_eap_sim_server_t *this, u_int32_t *vendor)
+{
+ *vendor = 0;
+ return EAP_SIM;
+}
+
+/**
+ * Implementation of eap_method_t.get_msk.
+ */
+static status_t get_msk(private_eap_sim_server_t *this, chunk_t *msk)
+{
+ if (this->msk.ptr)
+ {
+ *msk = this->msk;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of eap_method_t.is_mutual.
+ */
+static bool is_mutual(private_eap_sim_server_t *this)
+{
+ return TRUE;
+}
+
+/**
+ * Implementation of eap_method_t.destroy.
+ */
+static void destroy(private_eap_sim_server_t *this)
+{
+ this->crypto->destroy(this->crypto);
+ this->permanent->destroy(this->permanent);
+ DESTROY_IF(this->pseudonym);
+ DESTROY_IF(this->reauth);
+ free(this->sreses.ptr);
+ free(this->nonce.ptr);
+ free(this->msk.ptr);
+ free(this->counter.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+eap_sim_server_t *eap_sim_server_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_sim_server_t *this = malloc_thing(private_eap_sim_server_t);
+
+ this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
+ this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
+ this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
+ this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
+ this->public.interface.destroy = (void(*)(eap_method_t*))destroy;
+
+ this->crypto = simaka_crypto_create();
+ if (!this->crypto)
+ {
+ free(this);
+ return NULL;
+ }
+ this->permanent = peer->clone(peer);
+ this->pseudonym = NULL;
+ this->reauth = NULL;
+ this->sreses = chunk_empty;
+ this->nonce = chunk_empty;
+ this->msk = chunk_empty;
+ this->counter = chunk_empty;
+ this->pending = 0;
+ this->use_reauth = this->use_pseudonym = this->use_permanent =
+ lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-sim.request_identity", TRUE);
+
+ /* generate a non-zero identifier */
+ do {
+ this->identifier = random();
+ } while (!this->identifier);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.h b/src/libcharon/plugins/eap_sim/eap_sim_server.h
new file mode 100644
index 000000000..978e1e1e9
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.h
@@ -0,0 +1,57 @@
+/*
+ * 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 eap_sim_server eap_sim_server
+ * @{ @ingroup eap_sim
+ */
+
+#ifndef EAP_SIM_SERVER_H_
+#define EAP_SIM_SERVER_H_
+
+#include <sa/authenticators/eap/eap_method.h>
+
+typedef struct eap_sim_server_t eap_sim_server_t;
+
+/**
+ * EAP-SIM server implementation.
+ *
+ * This EAP-SIM module uses sim_provider_t implementations for triplet
+ * calculation, found via the eap_sim_manager_t.
+ */
+struct eap_sim_server_t {
+
+ /**
+ * Implemented eap_method_t interface.
+ */
+ eap_method_t interface;
+
+ /**
+ * Destroy a eap_sim_server_t.
+ */
+ void (*destroy)(eap_sim_server_t *this);
+};
+
+/**
+ * Creates the EAP method EAP-SIM acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP peer
+ * @return eap_sim_t object
+ */
+eap_sim_server_t *eap_sim_server_create(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_SIM_SERVER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am
new file mode 100644
index 000000000..2b59a7c88
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la
+endif
+
+libstrongswan_eap_sim_file_la_SOURCES = \
+ eap_sim_file_plugin.h eap_sim_file_plugin.c \
+ eap_sim_file_card.h eap_sim_file_card.c \
+ eap_sim_file_provider.h eap_sim_file_provider.c \
+ eap_sim_file_triplets.h eap_sim_file_triplets.c
+
+libstrongswan_eap_sim_file_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
new file mode 100644
index 000000000..2d998dbcc
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -0,0 +1,595 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_sim_file
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_sim_file_la_LIBADD =
+am_libstrongswan_eap_sim_file_la_OBJECTS = eap_sim_file_plugin.lo \
+ eap_sim_file_card.lo eap_sim_file_provider.lo \
+ eap_sim_file_triplets.lo
+libstrongswan_eap_sim_file_la_OBJECTS = \
+ $(am_libstrongswan_eap_sim_file_la_OBJECTS)
+libstrongswan_eap_sim_file_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_sim_file_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_file_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_file_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_sim_file_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_sim_file_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la
+libstrongswan_eap_sim_file_la_SOURCES = \
+ eap_sim_file_plugin.h eap_sim_file_plugin.c \
+ eap_sim_file_card.h eap_sim_file_card.c \
+ eap_sim_file_provider.h eap_sim_file_provider.c \
+ eap_sim_file_triplets.h eap_sim_file_triplets.c
+
+libstrongswan_eap_sim_file_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim_file/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim_file/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-sim-file.la: $(libstrongswan_eap_sim_file_la_OBJECTS) $(libstrongswan_eap_sim_file_la_DEPENDENCIES)
+ $(libstrongswan_eap_sim_file_la_LINK) $(am_libstrongswan_eap_sim_file_la_rpath) $(libstrongswan_eap_sim_file_la_OBJECTS) $(libstrongswan_eap_sim_file_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file_card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file_provider.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file_triplets.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
new file mode 100644
index 000000000..d132a38f6
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008-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 "eap_sim_file_card.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_sim_file_card_t private_eap_sim_file_card_t;
+
+/**
+ * Private data of an eap_sim_file_card_t object.
+ */
+struct private_eap_sim_file_card_t {
+
+ /**
+ * Public eap_sim_file_card_t interface.
+ */
+ eap_sim_file_card_t public;
+
+ /**
+ * source of triplets
+ */
+ eap_sim_file_triplets_t *triplets;
+};
+
+/**
+ * Implementation of sim_card_t.get_triplet
+ */
+static bool get_triplet(private_eap_sim_file_card_t *this,
+ identification_t *id, char *rand, char *sres, char *kc)
+{
+ enumerator_t *enumerator;
+ identification_t *cand;
+ char *c_rand, *c_sres, *c_kc;
+
+ DBG2(DBG_CFG, "looking for triplet: %Y rand %b", id, rand, SIM_RAND_LEN);
+
+ enumerator = this->triplets->create_enumerator(this->triplets);
+ while (enumerator->enumerate(enumerator, &cand, &c_rand, &c_sres, &c_kc))
+ {
+ DBG2(DBG_CFG, "got a triplet: %Y rand %b\nsres %b\n kc %b", cand,
+ c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
+ if (id->matches(id, cand))
+ {
+ if (memeq(c_rand, rand, SIM_RAND_LEN))
+ {
+ DBG2(DBG_CFG, " => triplet matches");
+ memcpy(sres, c_sres, SIM_SRES_LEN);
+ memcpy(kc, c_kc, SIM_KC_LEN);
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_card_t.get_quintuplet
+ */
+static status_t get_quintuplet()
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Implementation of eap_sim_file_card_t.destroy.
+ */
+static void destroy(private_eap_sim_file_card_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets)
+{
+ private_eap_sim_file_card_t *this = malloc_thing(private_eap_sim_file_card_t);
+
+ this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet;
+ this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet;
+ this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))return_null;
+ this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop;
+ this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop;
+ this->public.destroy = (void(*)(eap_sim_file_card_t*))destroy;
+
+ this->triplets = triplets;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h
new file mode 100644
index 000000000..1a5470968
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_sim_file_card eap_sim_file_card
+ * @{ @ingroup eap_sim_file
+ */
+
+#ifndef EAP_SIM_FILE_CARD_H_
+#define EAP_SIM_FILE_CARD_H_
+
+#include "eap_sim_file_triplets.h"
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_sim_file_card_t eap_sim_file_card_t;
+
+/**
+ * SIM card implementation on top of a triplet file.
+ */
+struct eap_sim_file_card_t {
+
+ /**
+ * Implements sim_card_t interface
+ */
+ sim_card_t card;
+
+ /**
+ * Destroy a eap_sim_file_card_t.
+ */
+ void (*destroy)(eap_sim_file_card_t *this);
+};
+
+/**
+ * Create a eap_sim_file_card instance.
+ *
+ * @param triplets source of triplets
+ */
+eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets);
+
+#endif /** EAP_SIM_FILE_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c
new file mode 100644
index 000000000..4f25c35ea
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include "eap_sim_file_plugin.h"
+#include "eap_sim_file_card.h"
+#include "eap_sim_file_provider.h"
+#include "eap_sim_file_triplets.h"
+
+#include <daemon.h>
+
+#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat"
+
+typedef struct private_eap_sim_file_t private_eap_sim_file_t;
+
+/**
+ * Private data of an eap_sim_file_t object.
+ */
+struct private_eap_sim_file_t {
+
+ /**
+ * Public eap_sim_file_plugin_t interface.
+ */
+ eap_sim_file_plugin_t public;
+
+ /**
+ * SIM card
+ */
+ eap_sim_file_card_t *card;
+
+ /**
+ * SIM provider
+ */
+ eap_sim_file_provider_t *provider;
+
+ /**
+ * Triplet source
+ */
+ eap_sim_file_triplets_t *triplets;
+};
+
+/**
+ * Implementation of eap_sim_file_t.destroy.
+ */
+static void destroy(private_eap_sim_file_t *this)
+{
+ charon->sim->remove_card(charon->sim, &this->card->card);
+ charon->sim->remove_provider(charon->sim, &this->provider->provider);
+ this->card->destroy(this->card);
+ this->provider->destroy(this->provider);
+ this->triplets->destroy(this->triplets);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_sim_file_plugin_create()
+{
+ private_eap_sim_file_t *this = malloc_thing(private_eap_sim_file_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->triplets = eap_sim_file_triplets_create(TRIPLET_FILE);
+ this->provider = eap_sim_file_provider_create(this->triplets);
+ if (!this->provider)
+ {
+ this->triplets->destroy(this->triplets);
+ free(this);
+ return NULL;
+ }
+ this->card = eap_sim_file_card_create(this->triplets);
+
+ charon->sim->add_card(charon->sim, &this->card->card);
+ charon->sim->add_provider(charon->sim, &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.h
new file mode 100644
index 000000000..f5083c72f
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_sim_file eap_sim_file
+ * @ingroup cplugins
+ *
+ * @defgroup eap_sim_file_plugin eap_sim_file_plugin
+ * @{ @ingroup eap_sim_file
+ */
+
+#ifndef EAP_SIM_FILE_PLUGIN_H_
+#define EAP_SIM_FILE_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_sim_file_plugin_t eap_sim_file_plugin_t;
+
+/**
+ * Plugin to provide a SIM card/provider on top of a triplet file.
+ */
+struct eap_sim_file_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_SIM_FILE_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c
new file mode 100644
index 000000000..9bee31fc3
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008-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 "eap_sim_file_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_sim_file_provider_t private_eap_sim_file_provider_t;
+
+/**
+ * Private data of an eap_sim_file_provider_t object.
+ */
+struct private_eap_sim_file_provider_t {
+
+ /**
+ * Public eap_sim_file_provider_t interface.
+ */
+ eap_sim_file_provider_t public;
+
+ /**
+ * source of triplets
+ */
+ eap_sim_file_triplets_t *triplets;
+};
+
+/**
+ * Implementation of sim_provider_t.get_triplet
+ */
+static bool get_triplet(private_eap_sim_file_provider_t *this,
+ identification_t *id, char *rand, char *sres, char *kc)
+{
+ enumerator_t *enumerator;
+ identification_t *cand;
+ char *c_rand, *c_sres, *c_kc;
+
+ enumerator = this->triplets->create_enumerator(this->triplets);
+ while (enumerator->enumerate(enumerator, &cand, &c_rand, &c_sres, &c_kc))
+ {
+ if (id->matches(id, cand))
+ {
+ memcpy(rand, c_rand, SIM_RAND_LEN);
+ memcpy(sres, c_sres, SIM_SRES_LEN);
+ memcpy(kc, c_kc, SIM_KC_LEN);
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_sim_file_provider_t.destroy.
+ */
+static void destroy(private_eap_sim_file_provider_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_sim_file_provider_t *eap_sim_file_provider_create(
+ eap_sim_file_triplets_t *triplets)
+{
+ private_eap_sim_file_provider_t *this = malloc_thing(private_eap_sim_file_provider_t);
+
+ this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet;
+ this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false;
+ this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null;
+ this->public.destroy = (void(*)(eap_sim_file_provider_t*))destroy;
+
+ this->triplets = triplets;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h
new file mode 100644
index 000000000..10fda282a
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h
@@ -0,0 +1,50 @@
+/*
+ * 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 eap_sim_file_provider eap_sim_file_provider
+ * @{ @ingroup eap_sim_file
+ */
+
+#ifndef EAP_SIM_FILE_PROVIDER_H_
+#define EAP_SIM_FILE_PROVIDER_H_
+
+#include "eap_sim_file_triplets.h"
+
+typedef struct eap_sim_file_provider_t eap_sim_file_provider_t;
+
+/**
+ * SIM provider implementation on top of triplets file.
+ */
+struct eap_sim_file_provider_t {
+
+ /**
+ * Implements sim_provider_t interface.
+ */
+ sim_provider_t provider;
+
+ /**
+ * Destroy a eap_sim_file_provider_t.
+ */
+ void (*destroy)(eap_sim_file_provider_t *this);
+};
+
+/**
+ * Create a eap_sim_file_provider instance.
+ */
+eap_sim_file_provider_t *eap_sim_file_provider_create(
+ eap_sim_file_triplets_t *triplets);
+
+#endif /** EAP_SIM_FILE_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c
new file mode 100644
index 000000000..6b7d99fb7
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+#include "eap_sim_file_triplets.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/mutex.h>
+
+typedef struct private_eap_sim_file_triplets_t private_eap_sim_file_triplets_t;
+
+/**
+ * Private data of an eap_sim_file_triplets_t object.
+ */
+struct private_eap_sim_file_triplets_t {
+
+ /**
+ * Public eap_sim_file_triplets_t interface.
+ */
+ eap_sim_file_triplets_t public;
+
+ /**
+ * List of triplets, as triplet_t
+ */
+ linked_list_t *triplets;
+
+ /**
+ * mutex to lock triplets list
+ */
+ mutex_t *mutex;
+};
+
+/**
+ * A single triplet
+ */
+typedef struct {
+ identification_t *imsi;
+ char rand[SIM_RAND_LEN];
+ char sres[SIM_SRES_LEN];
+ char kc[SIM_KC_LEN];
+} triplet_t;
+
+/**
+ * Destroy a triplet
+ */
+static void triplet_destroy(triplet_t *this)
+{
+ DESTROY_IF(this->imsi);
+ free(this);
+}
+
+/**
+ * triplet enumerator
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner enumerator */
+ enumerator_t *inner;
+ /** current enumerating triplet */
+ triplet_t *current;
+ /** back ptr */
+ private_eap_sim_file_triplets_t *this;
+} triplet_enumerator_t;
+
+/**
+ * destroy a triplet enumerator
+ */
+static void enumerator_destroy(triplet_enumerator_t *e)
+{
+ if (e->current)
+ {
+ /* We assume that the current element is used on invocation if destroy.
+ * We move that triplet to the end to avoid handout of the same triplet
+ * next time. */
+ e->this->triplets->remove_at(e->this->triplets, e->inner);
+ e->this->triplets->insert_last(e->this->triplets, e->current);
+ }
+ e->inner->destroy(e->inner);
+ e->this->mutex->unlock(e->this->mutex);
+ free(e);
+}
+
+/**
+ * enumerate through triplets
+ */
+static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **imsi,
+ char **rand, char **sres, char **kc)
+{
+ triplet_t *triplet;
+
+ if (e->inner->enumerate(e->inner, &triplet))
+ {
+ e->current = triplet;
+ *imsi = triplet->imsi;
+ *rand = triplet->rand;
+ *sres = triplet->sres;
+ *kc = triplet->kc;
+ return TRUE;
+ }
+ e->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of eap_sim_file_triplets_t.create_enumerator
+ */
+static enumerator_t* create_enumerator(private_eap_sim_file_triplets_t *this)
+{
+ triplet_enumerator_t *enumerator = malloc_thing(triplet_enumerator_t);
+
+ this->mutex->lock(this->mutex);
+ enumerator->public.enumerate = (void*)enumerator_enumerate;
+ enumerator->public.destroy = (void*)enumerator_destroy;
+ enumerator->inner = this->triplets->create_enumerator(this->triplets);
+ enumerator->current = NULL;
+ enumerator->this = this;
+
+ return &enumerator->public;
+}
+
+/**
+ * convert to token into the array
+ */
+static void parse_token(char *to, char *from, size_t len)
+{
+ chunk_t chunk;
+
+ chunk = chunk_create(from, min(strlen(from), len * 2));
+ chunk = chunk_from_hex(chunk, NULL);
+ memset(to, 0, len);
+ memcpy(to + len - chunk.len, chunk.ptr, chunk.len);
+ free(chunk.ptr);
+}
+
+/**
+ * Read the triplets from the file
+ */
+static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
+{
+ char line[512];
+ FILE *file;
+ int i, nr = 0;
+
+ file = fopen(path, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_CFG, "opening triplet file %s failed: %s",
+ path, strerror(errno));
+ return;
+ }
+
+ /* read line by line */
+ while (fgets(line, sizeof(line), file))
+ {
+ triplet_t *triplet;
+ enumerator_t *enumerator;
+ char *token;
+
+ nr++;
+ /* skip comments, empty lines */
+ switch (line[0])
+ {
+ case '\n':
+ case '\r':
+ case '#':
+ case '\0':
+ continue;
+ default:
+ break;
+ }
+ triplet = malloc_thing(triplet_t);
+ memset(triplet, 0, sizeof(triplet_t));
+
+ i = 0;
+ enumerator = enumerator_create_token(line, ",", " \n\r#");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ switch (i++)
+ {
+ case 0: /* IMSI */
+ triplet->imsi = identification_create_from_string(token);
+ continue;
+ case 1: /* rand */
+ parse_token(triplet->rand, token, SIM_RAND_LEN);
+ continue;
+ case 2: /* sres */
+ parse_token(triplet->sres, token, SIM_SRES_LEN);
+ continue;
+ case 3: /* kc */
+ parse_token(triplet->kc, token, SIM_KC_LEN);
+ continue;
+ default:
+ break;;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+ if (i < 4)
+ {
+ DBG1(DBG_CFG, "error in triplet file, line %d", nr);
+ triplet_destroy(triplet);
+ continue;
+ }
+
+ DBG2(DBG_CFG, "triplet: imsi %Y\nrand %b\nsres %b\nkc %b",
+ triplet->imsi, triplet->rand, SIM_RAND_LEN,
+ triplet->sres, SIM_SRES_LEN, triplet->kc, SIM_KC_LEN);
+
+ this->triplets->insert_last(this->triplets, triplet);
+ }
+ fclose(file);
+
+ DBG1(DBG_CFG, "read %d triplets from %s",
+ this->triplets->get_count(this->triplets), path);
+}
+
+/**
+ * Implementation of eap_sim_file_triplets_t.destroy.
+ */
+static void destroy(private_eap_sim_file_triplets_t *this)
+{
+ this->triplets->destroy_function(this->triplets, (void*)triplet_destroy);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file)
+{
+ private_eap_sim_file_triplets_t *this = malloc_thing(private_eap_sim_file_triplets_t);
+
+ this->public.create_enumerator = (enumerator_t*(*)(eap_sim_file_triplets_t*))create_enumerator;
+ this->public.destroy = (void(*)(eap_sim_file_triplets_t*))destroy;
+
+ this->triplets = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ read_triplets(this, file);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h
new file mode 100644
index 000000000..8f8130810
--- /dev/null
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h
@@ -0,0 +1,56 @@
+/*
+ * 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 eap_sim_file_triplets eap_sim_file_triplets
+ * @{ @ingroup eap_sim_file
+ */
+
+#ifndef EAP_SIM_FILE_TRIPLETS_H_
+#define EAP_SIM_FILE_TRIPLETS_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_sim_file_triplets_t eap_sim_file_triplets_t;
+
+/**
+ * Reads triplets from a triplets.dat file.
+ *
+ * The file is in freeradius triplet file syntax:
+ * http://www.freeradius.org/radiusd/doc/rlm_sim_triplets
+ */
+struct eap_sim_file_triplets_t {
+
+ /**
+ * Create an enumerator over the file's triplets.
+ *
+ * @return enumerator over (identity, rand, sres, kc)
+ */
+ enumerator_t* (*create_enumerator)(eap_sim_file_triplets_t *this);
+
+ /**
+ * Destroy a eap_sim_file_triplets_t.
+ */
+ void (*destroy)(eap_sim_file_triplets_t *this);
+};
+
+/**
+ * Create a eap_sim_file_triplets instance.
+ *
+ * @param file triplet file to read from
+ */
+eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file);
+
+#endif /** EAP_SIM_FILE_TRIPLETS_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
new file mode 100644
index 000000000..a158d6dbe
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
+endif
+
+libstrongswan_eap_simaka_pseudonym_la_SOURCES = \
+ eap_simaka_pseudonym_plugin.h eap_simaka_pseudonym_plugin.c \
+ eap_simaka_pseudonym_card.h eap_simaka_pseudonym_card.c \
+ eap_simaka_pseudonym_provider.h eap_simaka_pseudonym_provider.c
+
+libstrongswan_eap_simaka_pseudonym_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
new file mode 100644
index 000000000..6c44ea2bb
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -0,0 +1,594 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_simaka_pseudonym
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_simaka_pseudonym_la_LIBADD =
+am_libstrongswan_eap_simaka_pseudonym_la_OBJECTS = \
+ eap_simaka_pseudonym_plugin.lo eap_simaka_pseudonym_card.lo \
+ eap_simaka_pseudonym_provider.lo
+libstrongswan_eap_simaka_pseudonym_la_OBJECTS = \
+ $(am_libstrongswan_eap_simaka_pseudonym_la_OBJECTS)
+libstrongswan_eap_simaka_pseudonym_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_simaka_pseudonym_la_LDFLAGS) $(LDFLAGS) -o \
+ $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_pseudonym_la_rpath = \
+@MONOLITHIC_FALSE@ -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_pseudonym_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_simaka_pseudonym_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_simaka_pseudonym_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
+libstrongswan_eap_simaka_pseudonym_la_SOURCES = \
+ eap_simaka_pseudonym_plugin.h eap_simaka_pseudonym_plugin.c \
+ eap_simaka_pseudonym_card.h eap_simaka_pseudonym_card.c \
+ eap_simaka_pseudonym_provider.h eap_simaka_pseudonym_provider.c
+
+libstrongswan_eap_simaka_pseudonym_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_pseudonym/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_pseudonym/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-simaka-pseudonym.la: $(libstrongswan_eap_simaka_pseudonym_la_OBJECTS) $(libstrongswan_eap_simaka_pseudonym_la_DEPENDENCIES)
+ $(libstrongswan_eap_simaka_pseudonym_la_LINK) $(am_libstrongswan_eap_simaka_pseudonym_la_rpath) $(libstrongswan_eap_simaka_pseudonym_la_OBJECTS) $(libstrongswan_eap_simaka_pseudonym_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_pseudonym_card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_pseudonym_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_pseudonym_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c
new file mode 100644
index 000000000..9b0f1bc71
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c
@@ -0,0 +1,154 @@
+/*
+ * 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 "eap_simaka_pseudonym_card.h"
+
+#include <daemon.h>
+#include <utils/hashtable.h>
+
+typedef struct private_eap_simaka_pseudonym_card_t private_eap_simaka_pseudonym_card_t;
+
+/**
+ * Private data of an eap_simaka_pseudonym_card_t object.
+ */
+struct private_eap_simaka_pseudonym_card_t {
+
+ /**
+ * Public eap_simaka_pseudonym_card_t interface.
+ */
+ eap_simaka_pseudonym_card_t public;
+
+ /**
+ * Permanent -> pseudonym mappings
+ */
+ hashtable_t *pseudonym;
+
+ /**
+ * Reverse pseudonym -> permanent mappings
+ */
+ hashtable_t *permanent;
+};
+
+/**
+ * hashtable hash function
+ */
+static u_int hash(identification_t *key)
+{
+ return chunk_hash(key->get_encoding(key));
+}
+
+/**
+ * hashtable equals function
+ */
+static bool equals(identification_t *key1, identification_t *key2)
+{
+ return key1->equals(key1, key2);
+}
+
+/**
+ * Implementation of sim_card_t.get_pseudonym
+ */
+static identification_t *get_pseudonym(private_eap_simaka_pseudonym_card_t *this,
+ identification_t *id)
+{
+ identification_t *pseudonym;
+
+ pseudonym = this->pseudonym->get(this->pseudonym, id);
+ if (pseudonym)
+ {
+ return pseudonym->clone(pseudonym);
+ }
+ return NULL;
+}
+
+/**
+ * Implementation of sim_card_t.set_pseudonym
+ */
+static void set_pseudonym(private_eap_simaka_pseudonym_card_t *this,
+ identification_t *id, identification_t *pseudonym)
+{
+ identification_t *permanent;
+
+ /* create new entries */
+ id = id->clone(id);
+ pseudonym = pseudonym->clone(pseudonym);
+ permanent = this->permanent->put(this->permanent, pseudonym, id);
+ pseudonym = this->pseudonym->put(this->pseudonym, id, pseudonym);
+
+ /* delete old entries */
+ DESTROY_IF(permanent);
+ DESTROY_IF(pseudonym);
+}
+
+/**
+ * Implementation of sim_card_t.get_quintuplet
+ */
+static status_t get_quintuplet()
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Implementation of eap_simaka_pseudonym_card_t.destroy.
+ */
+static void destroy(private_eap_simaka_pseudonym_card_t *this)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+ void *key;
+
+ enumerator = this->pseudonym->create_enumerator(this->pseudonym);
+ while (enumerator->enumerate(enumerator, &key, &id))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->permanent->create_enumerator(this->permanent);
+ while (enumerator->enumerate(enumerator, &key, &id))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ this->pseudonym->destroy(this->pseudonym);
+ this->permanent->destroy(this->permanent);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_pseudonym_card_t *eap_simaka_pseudonym_card_create()
+{
+ private_eap_simaka_pseudonym_card_t *this;
+
+ this = malloc_thing(private_eap_simaka_pseudonym_card_t);
+
+ this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false;
+ this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet;
+ this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))get_pseudonym;
+ this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))set_pseudonym;
+ this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop;
+ this->public.destroy = (void(*)(eap_simaka_pseudonym_card_t*))destroy;
+
+ this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0);
+ this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h
new file mode 100644
index 000000000..1b5940fdc
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h
@@ -0,0 +1,49 @@
+/*
+ * 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 eap_simaka_pseudonym_card eap_simaka_pseudonym_card
+ * @{ @ingroup eap_simaka_pseudonym
+ */
+
+#ifndef EAP_SIMAKA_PSEUDONYM_CARD_H_
+#define EAP_SIMAKA_PSEUDONYM_CARD_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_pseudonym_card_t eap_simaka_pseudonym_card_t;
+
+/**
+ * SIM card implementing volatile in-memory pseudonym storage.
+ */
+struct eap_simaka_pseudonym_card_t {
+
+ /**
+ * Implements sim_card_t interface
+ */
+ sim_card_t card;
+
+ /**
+ * Destroy a eap_simaka_pseudonym_card_t.
+ */
+ void (*destroy)(eap_simaka_pseudonym_card_t *this);
+};
+
+/**
+ * Create a eap_simaka_pseudonym_card instance.
+ */
+eap_simaka_pseudonym_card_t *eap_simaka_pseudonym_card_create();
+
+#endif /** EAP_SIMAKA_PSEUDONYM_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c
new file mode 100644
index 000000000..81b9d7b00
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c
@@ -0,0 +1,81 @@
+/*
+ * 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 "eap_simaka_pseudonym_plugin.h"
+#include "eap_simaka_pseudonym_card.h"
+#include "eap_simaka_pseudonym_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_pseudonym_t private_eap_simaka_pseudonym_t;
+
+/**
+ * Private data of an eap_simaka_pseudonym_t object.
+ */
+struct private_eap_simaka_pseudonym_t {
+
+ /**
+ * Public eap_simaka_pseudonym_plugin_t interface.
+ */
+ eap_simaka_pseudonym_plugin_t public;
+
+ /**
+ * SIM card
+ */
+ eap_simaka_pseudonym_card_t *card;
+
+ /**
+ * SIM provider
+ */
+ eap_simaka_pseudonym_provider_t *provider;
+};
+
+/**
+ * Implementation of eap_simaka_pseudonym_t.destroy.
+ */
+static void destroy(private_eap_simaka_pseudonym_t *this)
+{
+ charon->sim->remove_card(charon->sim, &this->card->card);
+ charon->sim->remove_provider(charon->sim, &this->provider->provider);
+ this->card->destroy(this->card);
+ this->provider->destroy(this->provider);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_simaka_pseudonym_plugin_create()
+{
+ private_eap_simaka_pseudonym_t *this;
+
+ this = malloc_thing(private_eap_simaka_pseudonym_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->provider = eap_simaka_pseudonym_provider_create();
+ if (!this->provider)
+ {
+ free(this);
+ return NULL;
+ }
+ this->card = eap_simaka_pseudonym_card_create();
+
+ charon->sim->add_card(charon->sim, &this->card->card);
+ charon->sim->add_provider(charon->sim, &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.h b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.h
new file mode 100644
index 000000000..1992b2482
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_simaka_pseudonym eap_simaka_pseudonym
+ * @ingroup cplugins
+ *
+ * @defgroup eap_simaka_pseudonym_plugin eap_simaka_pseudonym_plugin
+ * @{ @ingroup eap_simaka_pseudonym
+ */
+
+#ifndef EAP_SIMAKA_PSEUDONYM_PLUGIN_H_
+#define EAP_SIMAKA_PSEUDONYM_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_simaka_pseudonym_plugin_t eap_simaka_pseudonym_plugin_t;
+
+/**
+ * Plugin to provide in-memory storage of EAP-SIM/AKA pseudonyms.
+ */
+struct eap_simaka_pseudonym_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_SIMAKA_PSEUDONYM_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c
new file mode 100644
index 000000000..0613b8807
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c
@@ -0,0 +1,182 @@
+/*
+ * 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 "eap_simaka_pseudonym_provider.h"
+
+#include <utils/hashtable.h>
+
+typedef struct private_eap_simaka_pseudonym_provider_t private_eap_simaka_pseudonym_provider_t;
+
+/**
+ * Private data of an eap_simaka_pseudonym_provider_t object.
+ */
+struct private_eap_simaka_pseudonym_provider_t {
+
+ /**
+ * Public eap_simaka_pseudonym_provider_t interface.
+ */
+ eap_simaka_pseudonym_provider_t public;
+
+ /**
+ * Permanent -> pseudonym mappings
+ */
+ hashtable_t *pseudonym;
+
+ /**
+ * Reverse pseudonym -> permanent mappings
+ */
+ hashtable_t *permanent;
+
+ /**
+ * RNG for pseudonyms/reauth identities
+ */
+ rng_t *rng;
+};
+
+/**
+ * hashtable hash function
+ */
+static u_int hash(identification_t *key)
+{
+ return chunk_hash(key->get_encoding(key));
+}
+
+/**
+ * hashtable equals function
+ */
+static bool equals(identification_t *key1, identification_t *key2)
+{
+ return key1->equals(key1, key2);
+}
+
+/**
+ * Implementation of sim_provider_t.is_pseudonym
+ */
+static identification_t* is_pseudonym(
+ private_eap_simaka_pseudonym_provider_t *this, identification_t *id)
+{
+ identification_t *permanent;
+
+ permanent = this->permanent->get(this->permanent, id);
+ if (permanent)
+ {
+ return permanent->clone(permanent);
+ }
+ return NULL;
+}
+
+/**
+ * Generate a random identity
+ */
+static identification_t *gen_identity(
+ private_eap_simaka_pseudonym_provider_t *this)
+{
+ char buf[8], hex[sizeof(buf) * 2 + 1];
+
+ this->rng->get_bytes(this->rng, sizeof(buf), buf);
+ chunk_to_hex(chunk_create(buf, sizeof(buf)), hex, FALSE);
+
+ return identification_create_from_string(hex);
+}
+
+/**
+ * Implementation of sim_provider_t.get_pseudonym
+ */
+static identification_t* gen_pseudonym(
+ private_eap_simaka_pseudonym_provider_t *this, identification_t *id)
+{
+ identification_t *pseudonym, *permanent;
+
+ /* remove old entry */
+ pseudonym = this->pseudonym->remove(this->pseudonym, id);
+ if (pseudonym)
+ {
+ permanent = this->permanent->remove(this->permanent, pseudonym);
+ if (permanent)
+ {
+ permanent->destroy(permanent);
+ }
+ pseudonym->destroy(pseudonym);
+ }
+
+ pseudonym = gen_identity(this);
+
+ /* create new entries */
+ id = id->clone(id);
+ this->pseudonym->put(this->pseudonym, id, pseudonym);
+ this->permanent->put(this->permanent, pseudonym, id);
+
+ return pseudonym->clone(pseudonym);
+}
+
+/**
+ * Implementation of eap_simaka_pseudonym_provider_t.destroy.
+ */
+static void destroy(private_eap_simaka_pseudonym_provider_t *this)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+ void *key;
+
+ enumerator = this->pseudonym->create_enumerator(this->pseudonym);
+ while (enumerator->enumerate(enumerator, &key, &id))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->permanent->create_enumerator(this->permanent);
+ while (enumerator->enumerate(enumerator, &key, &id))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ this->pseudonym->destroy(this->pseudonym);
+ this->permanent->destroy(this->permanent);
+ this->rng->destroy(this->rng);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_pseudonym_provider_t *eap_simaka_pseudonym_provider_create()
+{
+ private_eap_simaka_pseudonym_provider_t *this;
+
+ this = malloc_thing(private_eap_simaka_pseudonym_provider_t);
+
+ this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false;
+ this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false;
+ this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))is_pseudonym;
+ this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))gen_pseudonym;
+ this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null;
+ this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null;
+ this->public.destroy = (void(*)(eap_simaka_pseudonym_provider_t*))destroy;
+
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!this->rng)
+ {
+ free(this);
+ return NULL;
+ }
+ this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0);
+ this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h
new file mode 100644
index 000000000..5d8e6d221
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h
@@ -0,0 +1,49 @@
+/*
+ * 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 eap_simaka_pseudonym_provider eap_simaka_pseudonym_provider
+ * @{ @ingroup eap_simaka_pseudonym
+ */
+
+#ifndef EAP_SIMAKA_PSEDUONYM_PROVIDER_H_
+#define EAP_SIMAKA_PSEDUONYM_PROVIDER_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_pseudonym_provider_t eap_simaka_pseudonym_provider_t;
+
+/**
+ * SIM provider implementing volatile in-memory pseudonym storage.
+ */
+struct eap_simaka_pseudonym_provider_t {
+
+ /**
+ * Implements sim_provider_t interface.
+ */
+ sim_provider_t provider;
+
+ /**
+ * Destroy a eap_simaka_pseudonym_provider_t.
+ */
+ void (*destroy)(eap_simaka_pseudonym_provider_t *this);
+};
+
+/**
+ * Create a eap_simaka_pseudonym_provider instance.
+ */
+eap_simaka_pseudonym_provider_t *eap_simaka_pseudonym_provider_create();
+
+#endif /** EAP_SIMAKA_PSEDUONYM_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
new file mode 100644
index 000000000..fbcd544d3
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
+endif
+
+libstrongswan_eap_simaka_reauth_la_SOURCES = \
+ eap_simaka_reauth_plugin.h eap_simaka_reauth_plugin.c \
+ eap_simaka_reauth_card.h eap_simaka_reauth_card.c \
+ eap_simaka_reauth_provider.h eap_simaka_reauth_provider.c
+
+libstrongswan_eap_simaka_reauth_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
new file mode 100644
index 000000000..35d8e7c3b
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -0,0 +1,593 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/eap_simaka_reauth
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_simaka_reauth_la_LIBADD =
+am_libstrongswan_eap_simaka_reauth_la_OBJECTS = \
+ eap_simaka_reauth_plugin.lo eap_simaka_reauth_card.lo \
+ eap_simaka_reauth_provider.lo
+libstrongswan_eap_simaka_reauth_la_OBJECTS = \
+ $(am_libstrongswan_eap_simaka_reauth_la_OBJECTS)
+libstrongswan_eap_simaka_reauth_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_simaka_reauth_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_reauth_la_rpath = \
+@MONOLITHIC_FALSE@ -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_reauth_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_simaka_reauth_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_simaka_reauth_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
+libstrongswan_eap_simaka_reauth_la_SOURCES = \
+ eap_simaka_reauth_plugin.h eap_simaka_reauth_plugin.c \
+ eap_simaka_reauth_card.h eap_simaka_reauth_card.c \
+ eap_simaka_reauth_provider.h eap_simaka_reauth_provider.c
+
+libstrongswan_eap_simaka_reauth_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_reauth/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_reauth/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-simaka-reauth.la: $(libstrongswan_eap_simaka_reauth_la_OBJECTS) $(libstrongswan_eap_simaka_reauth_la_DEPENDENCIES)
+ $(libstrongswan_eap_simaka_reauth_la_LINK) $(am_libstrongswan_eap_simaka_reauth_la_rpath) $(libstrongswan_eap_simaka_reauth_la_OBJECTS) $(libstrongswan_eap_simaka_reauth_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_reauth_card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_reauth_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_reauth_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c
new file mode 100644
index 000000000..14d0416d9
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c
@@ -0,0 +1,170 @@
+/*
+ * 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 "eap_simaka_reauth_card.h"
+
+#include <daemon.h>
+#include <utils/hashtable.h>
+
+typedef struct private_eap_simaka_reauth_card_t private_eap_simaka_reauth_card_t;
+
+/**
+ * Private data of an eap_simaka_reauth_card_t object.
+ */
+struct private_eap_simaka_reauth_card_t {
+
+ /**
+ * Public eap_simaka_reauth_card_t interface.
+ */
+ eap_simaka_reauth_card_t public;
+
+ /**
+ * Permanent -> reauth_data_t mappings
+ */
+ hashtable_t *reauth;
+};
+
+/**
+ * Data associated to a reauthentication identity
+ */
+typedef struct {
+ /** currently used reauthentication identity */
+ identification_t *id;
+ /** associated permanent identity */
+ identification_t *permanent;
+ /** counter value */
+ u_int16_t counter;
+ /** master key */
+ char mk[HASH_SIZE_SHA1];
+} reauth_data_t;
+
+/**
+ * hashtable hash function
+ */
+static u_int hash(identification_t *key)
+{
+ return chunk_hash(key->get_encoding(key));
+}
+
+/**
+ * hashtable equals function
+ */
+static bool equals(identification_t *key1, identification_t *key2)
+{
+ return key1->equals(key1, key2);
+}
+
+/**
+ * Implementation of sim_card_t.get_reauth
+ */
+static identification_t *get_reauth(private_eap_simaka_reauth_card_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter)
+{
+ reauth_data_t *data;
+ identification_t *reauth;
+
+ /* look up reauthentication data */
+ data = this->reauth->remove(this->reauth, id);
+ if (!data)
+ {
+ return NULL;
+ }
+ *counter = ++data->counter;
+ memcpy(mk, data->mk, HASH_SIZE_SHA1);
+ reauth = data->id;
+ data->permanent->destroy(data->permanent);
+ free(data);
+ return reauth;
+}
+
+/**
+ * Implementation of sim_card_t.set_reauth
+ */
+static void set_reauth(private_eap_simaka_reauth_card_t *this,
+ identification_t *id, identification_t* next,
+ char mk[HASH_SIZE_SHA1], u_int16_t counter)
+{
+ reauth_data_t *data;
+
+ data = this->reauth->get(this->reauth, id);
+ if (data)
+ {
+ data->id->destroy(data->id);
+ }
+ else
+ {
+ data = malloc_thing(reauth_data_t);
+ data->permanent = id->clone(id);
+ this->reauth->put(this->reauth, data->permanent, data);
+ }
+ data->counter = counter;
+ data->id = next->clone(next);
+ memcpy(data->mk, mk, HASH_SIZE_SHA1);
+}
+
+/**
+ * Implementation of sim_card_t.get_quintuplet
+ */
+static status_t get_quintuplet()
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Implementation of eap_simaka_reauth_card_t.destroy.
+ */
+static void destroy(private_eap_simaka_reauth_card_t *this)
+{
+ enumerator_t *enumerator;
+ reauth_data_t *data;
+ void *key;
+
+ enumerator = this->reauth->create_enumerator(this->reauth);
+ while (enumerator->enumerate(enumerator, &key, &data))
+ {
+ data->id->destroy(data->id);
+ data->permanent->destroy(data->permanent);
+ free(data);
+ }
+ enumerator->destroy(enumerator);
+
+ this->reauth->destroy(this->reauth);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_reauth_card_t *eap_simaka_reauth_card_create()
+{
+ private_eap_simaka_reauth_card_t *this;
+
+ this = malloc_thing(private_eap_simaka_reauth_card_t);
+
+ this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_null;
+ this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet;
+ this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))return_null;
+ this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop;
+ this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))get_reauth;
+ this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))set_reauth;
+ this->public.destroy = (void(*)(eap_simaka_reauth_card_t*))destroy;
+
+ this->reauth = hashtable_create((void*)hash, (void*)equals, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h
new file mode 100644
index 000000000..f24dc8a15
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h
@@ -0,0 +1,49 @@
+/*
+ * 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 eap_simaka_reauth_card eap_simaka_reauth_card
+ * @{ @ingroup eap_simaka_reauth
+ */
+
+#ifndef EAP_SIMAKA_REAUTH_CARD_H_
+#define EAP_SIMAKA_REAUTH_CARD_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_reauth_card_t eap_simaka_reauth_card_t;
+
+/**
+ * SIM card implementing volatile in-memory reauthentication data storage.
+ */
+struct eap_simaka_reauth_card_t {
+
+ /**
+ * Implements sim_card_t interface
+ */
+ sim_card_t card;
+
+ /**
+ * Destroy a eap_simaka_reauth_card_t.
+ */
+ void (*destroy)(eap_simaka_reauth_card_t *this);
+};
+
+/**
+ * Create a eap_simaka_reauth_card instance.
+ */
+eap_simaka_reauth_card_t *eap_simaka_reauth_card_create();
+
+#endif /** EAP_SIMAKA_REAUTH_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c
new file mode 100644
index 000000000..987a0e109
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c
@@ -0,0 +1,79 @@
+/*
+ * 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 "eap_simaka_reauth_plugin.h"
+#include "eap_simaka_reauth_card.h"
+#include "eap_simaka_reauth_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_reauth_t private_eap_simaka_reauth_t;
+
+/**
+ * Private data of an eap_simaka_reauth_t object.
+ */
+struct private_eap_simaka_reauth_t {
+
+ /**
+ * Public eap_simaka_reauth_plugin_t interface.
+ */
+ eap_simaka_reauth_plugin_t public;
+
+ /**
+ * SIM card
+ */
+ eap_simaka_reauth_card_t *card;
+
+ /**
+ * SIM provider
+ */
+ eap_simaka_reauth_provider_t *provider;
+};
+
+/**
+ * Implementation of eap_simaka_reauth_t.destroy.
+ */
+static void destroy(private_eap_simaka_reauth_t *this)
+{
+ charon->sim->remove_card(charon->sim, &this->card->card);
+ charon->sim->remove_provider(charon->sim, &this->provider->provider);
+ this->card->destroy(this->card);
+ this->provider->destroy(this->provider);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_simaka_reauth_plugin_create()
+{
+ private_eap_simaka_reauth_t *this = malloc_thing(private_eap_simaka_reauth_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->provider = eap_simaka_reauth_provider_create();
+ if (!this->provider)
+ {
+ free(this);
+ return NULL;
+ }
+ this->card = eap_simaka_reauth_card_create();
+
+ charon->sim->add_card(charon->sim, &this->card->card);
+ charon->sim->add_provider(charon->sim, &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.h b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.h
new file mode 100644
index 000000000..80c8a1037
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 eap_simaka_reauth eap_simaka_reauth
+ * @ingroup cplugins
+ *
+ * @defgroup eap_simaka_reauth_plugin eap_simaka_reauth_plugin
+ * @{ @ingroup eap_simaka_reauth
+ */
+
+#ifndef EAP_SIMAKA_REAUTH_PLUGIN_H_
+#define EAP_SIMAKA_REAUTH_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_simaka_reauth_plugin_t eap_simaka_reauth_plugin_t;
+
+/**
+ * Plugin to provide in-memory EAP-SIM/AKA reauthentication data storage.
+ */
+struct eap_simaka_reauth_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_SIMAKA_REAUTH_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c
new file mode 100644
index 000000000..f962b2d84
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c
@@ -0,0 +1,209 @@
+/*
+ * 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 "eap_simaka_reauth_provider.h"
+
+#include <daemon.h>
+#include <utils/hashtable.h>
+
+typedef struct private_eap_simaka_reauth_provider_t private_eap_simaka_reauth_provider_t;
+
+/**
+ * Private data of an eap_simaka_reauth_provider_t object.
+ */
+struct private_eap_simaka_reauth_provider_t {
+
+ /**
+ * Public eap_simaka_reauth_provider_t interface.
+ */
+ eap_simaka_reauth_provider_t public;
+
+ /**
+ * Permanent -> reauth_data_t mappings
+ */
+ hashtable_t *reauth;
+
+ /**
+ * Reverse reauth -> permanent mappings
+ */
+ hashtable_t *permanent;
+
+ /**
+ * RNG for pseudonyms/reauth identities
+ */
+ rng_t *rng;
+};
+
+/**
+ * Data associated to a reauthentication identity
+ */
+typedef struct {
+ /** currently used reauthentication identity */
+ identification_t *id;
+ /** counter value */
+ u_int16_t counter;
+ /** master key */
+ char mk[HASH_SIZE_SHA1];
+} reauth_data_t;
+
+/**
+ * hashtable hash function
+ */
+static u_int hash(identification_t *key)
+{
+ return chunk_hash(key->get_encoding(key));
+}
+
+/**
+ * hashtable equals function
+ */
+static bool equals(identification_t *key1, identification_t *key2)
+{
+ return key1->equals(key1, key2);
+}
+
+/**
+ * Generate a random identity
+ */
+static identification_t *gen_identity(private_eap_simaka_reauth_provider_t *this)
+{
+ char buf[8], hex[sizeof(buf) * 2 + 1];
+
+ this->rng->get_bytes(this->rng, sizeof(buf), buf);
+ chunk_to_hex(chunk_create(buf, sizeof(buf)), hex, FALSE);
+
+ return identification_create_from_string(hex);
+}
+
+/**
+ * Implementation of sim_provider_t.is_reauth
+ */
+static identification_t *is_reauth(private_eap_simaka_reauth_provider_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter)
+{
+ identification_t *permanent;
+ reauth_data_t *data;
+
+ /* look up permanent identity */
+ permanent = this->permanent->get(this->permanent, id);
+ if (!permanent)
+ {
+ return NULL;
+ }
+ /* look up reauthentication data */
+ data = this->reauth->get(this->reauth, permanent);
+ if (!data)
+ {
+ return NULL;
+ }
+ *counter = ++data->counter;
+ memcpy(mk, data->mk, HASH_SIZE_SHA1);
+ return permanent->clone(permanent);
+}
+
+/**
+ * Implementation of sim_provider_t.gen_reauth
+ */
+static identification_t *gen_reauth(private_eap_simaka_reauth_provider_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1])
+{
+ reauth_data_t *data;
+ identification_t *permanent;
+
+ data = this->reauth->get(this->reauth, id);
+ if (data)
+ { /* update existing entry */
+ permanent = this->permanent->remove(this->permanent, data->id);
+ if (permanent)
+ {
+ data->id->destroy(data->id);
+ data->id = gen_identity(this);
+ this->permanent->put(this->permanent, data->id, permanent);
+ }
+ }
+ else
+ { /* generate new entry */
+ data = malloc_thing(reauth_data_t);
+ data->counter = 0;
+ data->id = gen_identity(this);
+ id = id->clone(id);
+ this->reauth->put(this->reauth, id, data);
+ this->permanent->put(this->permanent, data->id, id);
+ }
+ memcpy(data->mk, mk, HASH_SIZE_SHA1);
+
+ return data->id->clone(data->id);
+}
+
+/**
+ * Implementation of eap_simaka_reauth_provider_t.destroy.
+ */
+static void destroy(private_eap_simaka_reauth_provider_t *this)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+ reauth_data_t *data;
+ void *key;
+
+ enumerator = this->permanent->create_enumerator(this->permanent);
+ while (enumerator->enumerate(enumerator, &key, &id))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->reauth->create_enumerator(this->reauth);
+ while (enumerator->enumerate(enumerator, &key, &data))
+ {
+ data->id->destroy(data->id);
+ free(data);
+ }
+ enumerator->destroy(enumerator);
+
+ this->permanent->destroy(this->permanent);
+ this->reauth->destroy(this->reauth);
+ this->rng->destroy(this->rng);
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_reauth_provider_t *eap_simaka_reauth_provider_create()
+{
+ private_eap_simaka_reauth_provider_t *this = malloc_thing(private_eap_simaka_reauth_provider_t);
+
+ this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false;
+ this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false;
+ this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
+ this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null;
+ this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))is_reauth;
+ this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))gen_reauth;
+ this->public.destroy = (void(*)(eap_simaka_reauth_provider_t*))destroy;
+
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!this->rng)
+ {
+ free(this);
+ return NULL;
+ }
+ this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
+ this->reauth = hashtable_create((void*)hash, (void*)equals, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h
new file mode 100644
index 000000000..7ae151a27
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h
@@ -0,0 +1,49 @@
+/*
+ * 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 eap_simaka_reauth_provider eap_simaka_reauth_provider
+ * @{ @ingroup eap_simaka_reauth
+ */
+
+#ifndef EAP_SIMAKA_REAUTH_PROVIDER_H_
+#define EAP_SIMAKA_REAUTH_PROVIDER_H_
+
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_reauth_provider_t eap_simaka_reauth_provider_t;
+
+/**
+ * SIM provider implementing volatile in-memory reauthentication data storage.
+ */
+struct eap_simaka_reauth_provider_t {
+
+ /**
+ * Implements sim_provider_t interface.
+ */
+ sim_provider_t provider;
+
+ /**
+ * Destroy a eap_simaka_reauth_provider_t.
+ */
+ void (*destroy)(eap_simaka_reauth_provider_t *this);
+};
+
+/**
+ * Create a eap_simaka_reauth_provider instance.
+ */
+eap_simaka_reauth_provider_t *eap_simaka_reauth_provider_create();
+
+#endif /** EAP_SIMAKA_REAUTH_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/farp/Makefile.am b/src/libcharon/plugins/farp/Makefile.am
new file mode 100644
index 000000000..42cd31879
--- /dev/null
+++ b/src/libcharon/plugins/farp/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-farp.la
+else
+plugin_LTLIBRARIES = libstrongswan-farp.la
+endif
+
+libstrongswan_farp_la_SOURCES = farp_plugin.h farp_plugin.c \
+ farp_listener.h farp_listener.c farp_spoofer.h farp_spoofer.c
+
+libstrongswan_farp_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
new file mode 100644
index 000000000..20ac77080
--- /dev/null
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -0,0 +1,587 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/farp
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_farp_la_LIBADD =
+am_libstrongswan_farp_la_OBJECTS = farp_plugin.lo farp_listener.lo \
+ farp_spoofer.lo
+libstrongswan_farp_la_OBJECTS = $(am_libstrongswan_farp_la_OBJECTS)
+libstrongswan_farp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_farp_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_farp_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_farp_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_farp_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_farp_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-farp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-farp.la
+libstrongswan_farp_la_SOURCES = farp_plugin.h farp_plugin.c \
+ farp_listener.h farp_listener.c farp_spoofer.h farp_spoofer.c
+
+libstrongswan_farp_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/farp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/farp/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-farp.la: $(libstrongswan_farp_la_OBJECTS) $(libstrongswan_farp_la_DEPENDENCIES)
+ $(libstrongswan_farp_la_LINK) $(am_libstrongswan_farp_la_rpath) $(libstrongswan_farp_la_OBJECTS) $(libstrongswan_farp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farp_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farp_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farp_spoofer.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/farp/farp_listener.c b/src/libcharon/plugins/farp/farp_listener.c
new file mode 100644
index 000000000..8eed49778
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_listener.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "farp_listener.h"
+
+#include <utils/hashtable.h>
+#include <threading/rwlock.h>
+
+typedef struct private_farp_listener_t private_farp_listener_t;
+
+/**
+ * Private data of an farp_listener_t object.
+ */
+struct private_farp_listener_t {
+
+ /**
+ * Public farp_listener_t interface.
+ */
+ farp_listener_t public;
+
+ /**
+ * Hashtable with active virtual IPs
+ */
+ hashtable_t *ips;
+
+ /**
+ * RWlock for IP list
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Hashtable hash function
+ */
+static u_int hash(host_t *key)
+{
+ return chunk_hash(key->get_address(key));
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(host_t *a, host_t *b)
+{
+ return a->ip_equals(a, b);
+}
+
+METHOD(listener_t, ike_updown, bool,
+ private_farp_listener_t *this, ike_sa_t *ike_sa, bool up)
+{
+ if (!up)
+ {
+ host_t *ip;
+
+ ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (ip)
+ {
+ this->lock->write_lock(this->lock);
+ ip = this->ips->remove(this->ips, ip);
+ this->lock->unlock(this->lock);
+ DESTROY_IF(ip);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(listener_t, message_hook, bool,
+ private_farp_listener_t *this, ike_sa_t *ike_sa,
+ message_t *message, bool incoming)
+{
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ message->get_exchange_type(message) == IKE_AUTH &&
+ !message->get_request(message))
+ {
+ host_t *ip;
+
+ ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (ip)
+ {
+ ip = ip->clone(ip);
+ this->lock->write_lock(this->lock);
+ ip = this->ips->put(this->ips, ip, ip);
+ this->lock->unlock(this->lock);
+ DESTROY_IF(ip);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(farp_listener_t, is_active, bool,
+ private_farp_listener_t *this, host_t *ip)
+{
+ bool active;
+
+ this->lock->read_lock(this->lock);
+ active = this->ips->get(this->ips, ip) != NULL;
+ this->lock->unlock(this->lock);
+ return active;
+}
+
+METHOD(farp_listener_t, destroy, void,
+ private_farp_listener_t *this)
+{
+ enumerator_t *enumerator;
+ host_t *key, *value;
+
+ enumerator = this->ips->create_enumerator(this->ips);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ value->destroy(value);
+ }
+ enumerator->destroy(enumerator);
+ this->ips->destroy(this->ips);
+
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * See header
+ */
+farp_listener_t *farp_listener_create()
+{
+ private_farp_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .ike_updown = _ike_updown,
+ .message = _message_hook,
+ },
+ .is_active = _is_active,
+ .destroy = _destroy,
+ },
+ .ips = hashtable_create((hashtable_hash_t)hash,
+ (hashtable_equals_t)equals, 8),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/farp/farp_listener.h b/src/libcharon/plugins/farp/farp_listener.h
new file mode 100644
index 000000000..bd96d7a1c
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_listener.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup farp_listener farp_listener
+ * @{ @ingroup farp
+ */
+
+#ifndef FARP_LISTENER_H_
+#define FARP_LISTENER_H_
+
+#include <utils/host.h>
+#include <bus/listeners/listener.h>
+
+typedef struct farp_listener_t farp_listener_t;
+
+/**
+ * Listener to register the set of IPs we spoof ARP responses for.
+ */
+struct farp_listener_t {
+
+ /**
+ * Implements listener_t interface.
+ */
+ listener_t listener;
+
+ /**
+ * Check if a given IP is currently used as virtual IP by a peer.
+ *
+ * @param ip IP to check
+ * @return TRUE if IP is an active virtual IP
+ */
+ bool (*is_active)(farp_listener_t *this, host_t *ip);
+
+ /**
+ * Destroy a farp_listener_t.
+ */
+ void (*destroy)(farp_listener_t *this);
+};
+
+/**
+ * Create a farp_listener instance.
+ */
+farp_listener_t *farp_listener_create();
+
+#endif /** FARP_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/farp/farp_plugin.c b/src/libcharon/plugins/farp/farp_plugin.c
new file mode 100644
index 000000000..01c2a39c8
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_plugin.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "farp_plugin.h"
+
+#include "farp_listener.h"
+#include "farp_spoofer.h"
+
+#include <daemon.h>
+
+typedef struct private_farp_plugin_t private_farp_plugin_t;
+
+/**
+ * private data of farp plugin
+ */
+struct private_farp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ farp_plugin_t public;
+
+ /**
+ * Listener registering active virtual IPs
+ */
+ farp_listener_t *listener;
+
+ /**
+ * Spoofer listening and spoofing ARP messages
+ */
+ farp_spoofer_t *spoofer;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_farp_plugin_t *this)
+{
+ DESTROY_IF(this->spoofer);
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *farp_plugin_create()
+{
+ private_farp_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .listener = farp_listener_create(),
+ );
+
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ this->spoofer = farp_spoofer_create(this->listener);
+ if (!this->spoofer)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/farp/farp_plugin.h b/src/libcharon/plugins/farp/farp_plugin.h
new file mode 100644
index 000000000..0246fcc2a
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup farp farp
+ * @ingroup cplugins
+ *
+ * @defgroup farp_plugin farp_plugin
+ * @{ @ingroup farp
+ */
+
+#ifndef FARP_PLUGIN_H_
+#define FARP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct farp_plugin_t farp_plugin_t;
+
+/**
+ * ARP faking plugin that responds to ARP requests to peers virtual IP.
+ */
+struct farp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** FARP_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c
new file mode 100644
index 000000000..29e64e32d
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_spoofer.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "farp_spoofer.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/filter.h>
+#include <sys/ioctl.h>
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_farp_spoofer_t private_farp_spoofer_t;
+
+/**
+ * Private data of an farp_spoofer_t object.
+ */
+struct private_farp_spoofer_t {
+
+ /**
+ * Public farp_spoofer_t interface.
+ */
+ farp_spoofer_t public;
+
+ /**
+ * Listener that knows active addresses
+ */
+ farp_listener_t *listener;
+
+ /**
+ * Callback job to read ARP requests
+ */
+ callback_job_t *job;
+
+ /**
+ * RAW socket for ARP requests
+ */
+ int skt;
+};
+
+/**
+ * IP over Ethernet ARP message
+ */
+typedef struct __attribute__((packed)) {
+ u_int16_t hardware_type;
+ u_int16_t protocol_type;
+ u_int8_t hardware_size;
+ u_int8_t protocol_size;
+ u_int16_t opcode;
+ u_int8_t sender_mac[6];
+ u_int8_t sender_ip[4];
+ u_int8_t target_mac[6];
+ u_int8_t target_ip[4];
+} arp_t;
+
+/**
+ * Send faked ARP response
+ */
+static void send_arp(private_farp_spoofer_t *this,
+ arp_t *arp, struct sockaddr_ll *addr)
+{
+ struct ifreq req;
+ char tmp[4];
+
+ req.ifr_ifindex = addr->sll_ifindex;
+ if (ioctl(this->skt, SIOCGIFNAME, &req) == 0 &&
+ ioctl(this->skt, SIOCGIFHWADDR, &req) == 0 &&
+ req.ifr_hwaddr.sa_family == ARPHRD_ETHER)
+ {
+ memcpy(arp->target_mac, arp->sender_mac, 6);
+ memcpy(arp->sender_mac, req.ifr_hwaddr.sa_data, 6);
+
+ memcpy(tmp, arp->sender_ip, 4);
+ memcpy(arp->sender_ip, arp->target_ip, 4);
+ memcpy(arp->target_ip, tmp, 4);
+
+ arp->opcode = htons(ARPOP_REPLY);
+
+ sendto(this->skt, arp, sizeof(*arp), 0,
+ (struct sockaddr*)addr, sizeof(*addr));
+ }
+}
+
+/**
+ * ARP request receiving
+ */
+static job_requeue_t receive_arp(private_farp_spoofer_t *this)
+{
+ struct sockaddr_ll addr;
+ socklen_t addr_len = sizeof(addr);
+ arp_t arp;
+ int oldstate;
+ ssize_t len;
+ host_t *ip;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->skt, &arp, sizeof(arp), 0,
+ (struct sockaddr*)&addr, &addr_len);
+ thread_cancelability(oldstate);
+
+ if (len == sizeof(arp))
+ {
+ ip = host_create_from_chunk(AF_INET,
+ chunk_create((char*)&arp.target_ip, 4), 0);
+ if (ip)
+ {
+ if (this->listener->is_active(this->listener, ip))
+ {
+ send_arp(this, &arp, &addr);
+ }
+ ip->destroy(ip);
+ }
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(farp_spoofer_t, destroy, void,
+ private_farp_spoofer_t *this)
+{
+ this->job->cancel(this->job);
+ close(this->skt);
+ free(this);
+}
+
+/**
+ * See header
+ */
+farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
+{
+ private_farp_spoofer_t *this;
+ struct sock_filter arp_request_filter_code[] = {
+ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, protocol_type)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_P_IP, 0, 9),
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, hardware_size)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 7),
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, protocol_size)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 4),
+ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3),
+ BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 28, 0, 1),
+ BPF_STMT(BPF_RET+BPF_A, 0),
+ BPF_STMT(BPF_RET+BPF_K, 0),
+ };
+ struct sock_fprog arp_request_filter = {
+ sizeof(arp_request_filter_code) / sizeof(struct sock_filter),
+ arp_request_filter_code,
+ };
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .listener = listener,
+ );
+
+ this->skt = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
+ if (this->skt == -1)
+ {
+ DBG1(DBG_NET, "opening ARP packet socket failed: %s", strerror(errno));
+ free(this);
+ return NULL;
+ }
+
+ if (setsockopt(this->skt, SOL_SOCKET, SO_ATTACH_FILTER,
+ &arp_request_filter, sizeof(arp_request_filter)) < 0)
+ {
+ DBG1(DBG_NET, "installing ARP packet filter failed: %s", strerror(errno));
+ close(this->skt);
+ free(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_arp,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/farp/farp_spoofer.h b/src/libcharon/plugins/farp/farp_spoofer.h
new file mode 100644
index 000000000..c91fb3b96
--- /dev/null
+++ b/src/libcharon/plugins/farp/farp_spoofer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup farp_spoofer farp_spoofer
+ * @{ @ingroup farp
+ */
+
+#ifndef FARP_SPOOFER_H_
+#define FARP_SPOOFER_H_
+
+#include "farp_listener.h"
+
+typedef struct farp_spoofer_t farp_spoofer_t;
+
+/**
+ * Listen to ARP requests and spoof responses, if required.
+ */
+struct farp_spoofer_t {
+
+ /**
+ * Destroy a farp_spoofer_t.
+ */
+ void (*destroy)(farp_spoofer_t *this);
+};
+
+/**
+ * Create a farp_spoofer instance.
+ *
+ * @param listener listener to check for addresses to spoof
+ * @return spoofer instance
+ */
+farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener);
+
+#endif /** FARP_SPOOFER_H_ @}*/
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am
new file mode 100644
index 000000000..74fe1f4c7
--- /dev/null
+++ b/src/libcharon/plugins/ha/Makefile.am
@@ -0,0 +1,25 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ha.la
+else
+plugin_LTLIBRARIES = libstrongswan-ha.la
+endif
+
+libstrongswan_ha_la_SOURCES = \
+ ha_plugin.h ha_plugin.c \
+ ha_message.h ha_message.c \
+ ha_socket.h ha_socket.c \
+ ha_tunnel.h ha_tunnel.c \
+ ha_dispatcher.h ha_dispatcher.c \
+ ha_segments.h ha_segments.c \
+ ha_kernel.h ha_kernel.c \
+ ha_ctl.h ha_ctl.c \
+ ha_ike.h ha_ike.c \
+ ha_child.h ha_child.c
+libstrongswan_ha_la_LDFLAGS = -module -avoid-version
+
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
new file mode 100644
index 000000000..c60d3bf56
--- /dev/null
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -0,0 +1,604 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/ha
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_ha_la_LIBADD =
+am_libstrongswan_ha_la_OBJECTS = ha_plugin.lo ha_message.lo \
+ ha_socket.lo ha_tunnel.lo ha_dispatcher.lo ha_segments.lo \
+ ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo
+libstrongswan_ha_la_OBJECTS = $(am_libstrongswan_ha_la_OBJECTS)
+libstrongswan_ha_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_ha_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_ha_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_ha_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_ha_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_ha_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ha.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ha.la
+libstrongswan_ha_la_SOURCES = \
+ ha_plugin.h ha_plugin.c \
+ ha_message.h ha_message.c \
+ ha_socket.h ha_socket.c \
+ ha_tunnel.h ha_tunnel.c \
+ ha_dispatcher.h ha_dispatcher.c \
+ ha_segments.h ha_segments.c \
+ ha_kernel.h ha_kernel.c \
+ ha_ctl.h ha_ctl.c \
+ ha_ike.h ha_ike.c \
+ ha_child.h ha_child.c
+
+libstrongswan_ha_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/ha/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/ha/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-ha.la: $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_DEPENDENCIES)
+ $(libstrongswan_ha_la_LINK) $(am_libstrongswan_ha_la_rpath) $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_child.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_ctl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_dispatcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_ike.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_kernel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_segments.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_tunnel.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c
new file mode 100644
index 000000000..2eb8e27f6
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_child.c
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#include "ha_child.h"
+
+typedef struct private_ha_child_t private_ha_child_t;
+
+/**
+ * Private data of an ha_child_t object.
+ */
+struct private_ha_child_t {
+
+ /**
+ * Public ha_child_t interface.
+ */
+ ha_child_t public;
+
+ /**
+ * socket we use for syncing
+ */
+ ha_socket_t *socket;
+
+ /**
+ * tunnel securing sync messages
+ */
+ ha_tunnel_t *tunnel;
+};
+
+/**
+ * Implementation of listener_t.child_keys
+ */
+static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r)
+{
+ ha_message_t *m;
+ chunk_t secret;
+ proposal_t *proposal;
+ u_int16_t alg, len;
+ linked_list_t *list;
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ { /* do not sync SA between nodes */
+ return TRUE;
+ }
+
+ m = ha_message_create(HA_CHILD_ADD);
+
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE));
+ m->add_attribute(m, HA_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE));
+ m->add_attribute(m, HA_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE));
+ m->add_attribute(m, HA_OUTBOUND_CPI, child_sa->get_cpi(child_sa, FALSE));
+ m->add_attribute(m, HA_IPSEC_MODE, child_sa->get_mode(child_sa));
+ m->add_attribute(m, HA_IPCOMP, child_sa->get_ipcomp(child_sa));
+ m->add_attribute(m, HA_CONFIG_NAME, child_sa->get_name(child_sa));
+
+ proposal = child_sa->get_proposal(child_sa);
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
+ {
+ m->add_attribute(m, HA_ALG_ENCR, alg);
+ if (len)
+ {
+ m->add_attribute(m, HA_ALG_ENCR_LEN, len);
+ }
+ }
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ m->add_attribute(m, HA_ALG_INTEG, alg);
+ }
+ m->add_attribute(m, HA_NONCE_I, nonce_i);
+ m->add_attribute(m, HA_NONCE_R, nonce_r);
+ if (dh && dh->get_shared_secret(dh, &secret) == SUCCESS)
+ {
+ m->add_attribute(m, HA_SECRET, secret);
+ chunk_clear(&secret);
+ }
+
+ list = child_sa->get_traffic_selectors(child_sa, TRUE);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ m->add_attribute(m, HA_LOCAL_TS, ts);
+ }
+ enumerator->destroy(enumerator);
+ list = child_sa->get_traffic_selectors(child_sa, FALSE);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ m->add_attribute(m, HA_REMOTE_TS, ts);
+ }
+ enumerator->destroy(enumerator);
+
+ this->socket->push(this->socket, m);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(private_ha_child_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (!ike_sa ||
+ ike_sa->get_state(ike_sa) == IKE_PASSIVE ||
+ ike_sa->get_state(ike_sa) == IKE_DESTROYING)
+ { /* only sync active IKE_SAs */
+ return TRUE;
+ }
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ { /* do not sync SA between nodes */
+ return TRUE;
+ }
+
+
+ if (state == CHILD_DESTROYING)
+ {
+ ha_message_t *m;
+
+ m = ha_message_create(HA_CHILD_DELETE);
+
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_INBOUND_SPI,
+ child_sa->get_spi(child_sa, TRUE));
+ this->socket->push(this->socket, m);
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of ha_child_t.destroy.
+ */
+static void destroy(private_ha_child_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
+{
+ private_ha_child_t *this = malloc_thing(private_ha_child_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.child_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
+ this->public.listener.child_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state))child_state_change;
+ this->public.destroy = (void(*)(ha_child_t*))destroy;
+
+ this->socket = socket;
+ this->tunnel = tunnel;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_child.h b/src/libcharon/plugins/ha/ha_child.h
new file mode 100644
index 000000000..ea83495f7
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_child.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ha_child ha_child
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_CHILD_H_
+#define HA_CHILD_H_
+
+#include "ha_socket.h"
+#include "ha_tunnel.h"
+#include "ha_segments.h"
+
+#include <daemon.h>
+
+typedef struct ha_child_t ha_child_t;
+
+/**
+ * Listener to synchronize CHILD_SAs.
+ */
+struct ha_child_t {
+
+ /**
+ * Implements bus listener interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a ha_child_t.
+ */
+ void (*destroy)(ha_child_t *this);
+};
+
+/**
+ * Create a ha_child instance.
+ *
+ * @param socket socket to use for sending synchronization messages
+ * @param tunnel tunnel securing sync messages, if any
+ * @return CHILD listener
+ */
+ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
+
+#endif /* HA_CHILD_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
new file mode 100644
index 000000000..441d26d9e
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#include "ha_ctl.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <processing/jobs/callback_job.h>
+
+#define HA_FIFO IPSEC_PIDDIR "/charon.ha"
+
+typedef struct private_ha_ctl_t private_ha_ctl_t;
+
+/**
+ * Private data of an ha_ctl_t object.
+ */
+struct private_ha_ctl_t {
+
+ /**
+ * Public ha_ctl_t interface.
+ */
+ ha_ctl_t public;
+
+ /**
+ * Segments to control
+ */
+ ha_segments_t *segments;
+
+ /**
+ * FIFO reader thread
+ */
+ callback_job_t *job;
+};
+
+/**
+ * FIFO dispatching function
+ */
+static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
+{
+ int fifo, old;
+ char buf[8];
+ u_int segment;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
+ fifo = open(HA_FIFO, O_RDONLY);
+ pthread_setcancelstate(old, NULL);
+ if (fifo == -1)
+ {
+ DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno));
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (read(fifo, buf, sizeof(buf)-1) > 1)
+ {
+ segment = atoi(&buf[1]);
+ if (segment)
+ {
+ switch (buf[0])
+ {
+ case '+':
+ this->segments->activate(this->segments, segment, TRUE);
+ break;
+ case '-':
+ this->segments->deactivate(this->segments, segment, TRUE);
+ break;
+ case '*':
+ this->segments->resync(this->segments, segment);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ close(fifo);
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implementation of ha_ctl_t.destroy.
+ */
+static void destroy(private_ha_ctl_t *this)
+{
+ this->job->cancel(this->job);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_ctl_t *ha_ctl_create(ha_segments_t *segments)
+{
+ private_ha_ctl_t *this = malloc_thing(private_ha_ctl_t);
+
+ this->public.destroy = (void(*)(ha_ctl_t*))destroy;
+
+ if (access(HA_FIFO, R_OK|W_OK) != 0)
+ {
+ if (mkfifo(HA_FIFO, 600) != 0)
+ {
+ DBG1(DBG_CFG, "creating HA FIFO %s failed: %s",
+ HA_FIFO, strerror(errno));
+ }
+ }
+
+ this->segments = segments;
+ this->job = callback_job_create((callback_job_cb_t)dispatch_fifo,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_ctl.h b/src/libcharon/plugins/ha/ha_ctl.h
new file mode 100644
index 000000000..f33a809be
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_ctl.h
@@ -0,0 +1,47 @@
+/*
+ * 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 ha_ctl ha_ctl
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_CTL_H_
+#define HA_CTL_H_
+
+#include "ha_segments.h"
+
+typedef struct ha_ctl_t ha_ctl_t;
+
+/**
+ * HA Sync control interface using a FIFO.
+ */
+struct ha_ctl_t {
+
+ /**
+ * Destroy a ha_ctl_t.
+ */
+ void (*destroy)(ha_ctl_t *this);
+};
+
+/**
+ * Create a ha_ctl instance.
+ *
+ * @param segments segments to control
+ * @return HA control interface
+ */
+ha_ctl_t *ha_ctl_create(ha_segments_t *segments);
+
+#endif /* HA_CTL_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
new file mode 100644
index 000000000..7df2f1fa8
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -0,0 +1,737 @@
+/*
+ * 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.
+ */
+
+#include "ha_dispatcher.h"
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
+
+/**
+ * Private data of an ha_dispatcher_t object.
+ */
+struct private_ha_dispatcher_t {
+
+ /**
+ * Public ha_dispatcher_t interface.
+ */
+ ha_dispatcher_t public;
+
+ /**
+ * socket to pull messages from
+ */
+ ha_socket_t *socket;
+
+ /**
+ * segments to control
+ */
+ ha_segments_t *segments;
+
+ /**
+ * Dispatcher job
+ */
+ callback_job_t *job;
+};
+
+/**
+ * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret
+ */
+static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret)
+{
+ *secret = chunk_clone((*(chunk_t*)this->destroy));
+ return SUCCESS;
+}
+
+/**
+ * Process messages of type IKE_ADD
+ */
+static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL, *old_sa = NULL;
+ u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
+ chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
+ chunk_t secret = chunk_empty, old_skd = chunk_empty;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = ike_sa_create(value.ike_sa_id);
+ break;
+ case HA_IKE_REKEY_ID:
+ old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_NONCE_I:
+ nonce_i = value.chunk;
+ break;
+ case HA_NONCE_R:
+ nonce_r = value.chunk;
+ break;
+ case HA_SECRET:
+ secret = value.chunk;
+ break;
+ case HA_OLD_SKD:
+ old_skd = value.chunk;
+ break;
+ case HA_ALG_ENCR:
+ encr = value.u16;
+ break;
+ case HA_ALG_ENCR_LEN:
+ len = value.u16;
+ break;
+ case HA_ALG_INTEG:
+ integ = value.u16;
+ break;
+ case HA_ALG_PRF:
+ prf = value.u16;
+ break;
+ case HA_ALG_OLD_PRF:
+ old_prf = value.u16;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ proposal_t *proposal;
+ keymat_t *keymat;
+ /* quick and dirty hack of a DH implementation ;-) */
+ diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
+ .destroy = (void*)&secret };
+
+ proposal = proposal_create(PROTO_IKE);
+ keymat = ike_sa->get_keymat(ike_sa);
+ if (integ)
+ {
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
+ }
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
+ }
+ if (prf)
+ {
+ proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ }
+ charon->bus->set_sa(charon->bus, ike_sa);
+ if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r,
+ ike_sa->get_id(ike_sa), old_prf, old_skd))
+ {
+ 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);
+ }
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, old_sa);
+ old_sa = NULL;
+ }
+ ike_sa->set_state(ike_sa, IKE_CONNECTING);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "HA keymat derivation failed");
+ ike_sa->destroy(ike_sa);
+ }
+ charon->bus->set_sa(charon->bus, NULL);
+ proposal->destroy(proposal);
+ }
+ if (old_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
+ }
+}
+
+/**
+ * Apply a condition flag to the IKE_SA if it is in set
+ */
+static void set_condition(ike_sa_t *ike_sa, ike_condition_t set,
+ ike_condition_t flag)
+{
+ ike_sa->set_condition(ike_sa, flag, flag & set);
+}
+
+/**
+ * Apply a extension flag to the IKE_SA if it is in set
+ */
+static void set_extension(ike_sa_t *ike_sa, ike_extension_t set,
+ ike_extension_t flag)
+{
+ if (flag & set)
+ {
+ ike_sa->enable_extension(ike_sa, flag);
+ }
+}
+
+/**
+ * Process messages of type IKE_UPDATE
+ */
+static void process_ike_update(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ peer_cfg_t *peer_cfg = NULL;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ if (attribute != HA_IKE_ID && ike_sa == NULL)
+ {
+ /* must be first attribute */
+ break;
+ }
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_LOCAL_ID:
+ ike_sa->set_my_id(ike_sa, value.id->clone(value.id));
+ break;
+ case HA_REMOTE_ID:
+ ike_sa->set_other_id(ike_sa, value.id->clone(value.id));
+ break;
+ case HA_LOCAL_ADDR:
+ ike_sa->set_my_host(ike_sa, value.host->clone(value.host));
+ break;
+ case HA_REMOTE_ADDR:
+ ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
+ break;
+ case HA_LOCAL_VIP:
+ ike_sa->set_virtual_ip(ike_sa, TRUE, value.host);
+ break;
+ case HA_REMOTE_VIP:
+ ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ break;
+ case HA_ADDITIONAL_ADDR:
+ ike_sa->add_additional_address(ike_sa,
+ value.host->clone(value.host));
+ break;
+ case HA_CONFIG_NAME:
+ peer_cfg = charon->backends->get_peer_cfg_by_name(
+ charon->backends, value.str);
+ if (peer_cfg)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ peer_cfg->destroy(peer_cfg);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "HA is missing nodes peer configuration");
+ }
+ break;
+ case HA_EXTENSIONS:
+ set_extension(ike_sa, value.u32, EXT_NATT);
+ set_extension(ike_sa, value.u32, EXT_MOBIKE);
+ set_extension(ike_sa, value.u32, EXT_HASH_AND_URL);
+ break;
+ case HA_CONDITIONS:
+ set_condition(ike_sa, value.u32, COND_NAT_ANY);
+ set_condition(ike_sa, value.u32, COND_NAT_HERE);
+ set_condition(ike_sa, value.u32, COND_NAT_THERE);
+ set_condition(ike_sa, value.u32, COND_NAT_FAKE);
+ set_condition(ike_sa, value.u32, COND_EAP_AUTHENTICATED);
+ set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN);
+ set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR);
+ break;
+ case HA_INITIATE_MID:
+ ike_sa->set_message_id(ike_sa, TRUE, value.u32);
+ break;
+ case HA_RESPOND_MID:
+ ike_sa->set_message_id(ike_sa, FALSE, value.u32);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
+ ike_sa->get_peer_cfg(ike_sa))
+ {
+ ike_sa->set_state(ike_sa, IKE_PASSIVE);
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+}
+
+/**
+ * Process messages of type IKE_DELETE
+ */
+static void process_ike_delete(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, value.ike_sa_id);
+ if (ike_sa)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Lookup a child cfg from the peer cfg by name
+ */
+static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found;
+}
+
+/**
+ * Process messages of type CHILD_ADD
+ */
+static void process_child_add(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ char *config_name = "";
+ child_cfg_t *config = NULL;
+ child_sa_t *child_sa;
+ proposal_t *proposal;
+ keymat_t *keymat;
+ bool initiator = FALSE, failed = FALSE;
+ u_int32_t inbound_spi = 0, outbound_spi = 0;
+ u_int16_t inbound_cpi = 0, outbound_cpi = 0;
+ u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
+ u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
+ chunk_t encr_i, integ_i, encr_r, integ_r;
+ linked_list_t *local_ts, *remote_ts;
+ /* quick and dirty hack of a DH implementation */
+ diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
+ .destroy = (void*)&secret };
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ initiator = value.ike_sa_id->is_initiator(value.ike_sa_id);
+ break;
+ case HA_CONFIG_NAME:
+ config_name = value.str;
+ break;
+ case HA_INBOUND_SPI:
+ inbound_spi = value.u32;
+ break;
+ case HA_OUTBOUND_SPI:
+ outbound_spi = value.u32;
+ break;
+ case HA_INBOUND_CPI:
+ inbound_cpi = value.u32;
+ break;
+ case HA_OUTBOUND_CPI:
+ outbound_cpi = value.u32;
+ break;
+ case HA_IPSEC_MODE:
+ mode = value.u8;
+ break;
+ case HA_IPCOMP:
+ ipcomp = value.u8;
+ break;
+ case HA_ALG_ENCR:
+ encr = value.u16;
+ break;
+ case HA_ALG_ENCR_LEN:
+ len = value.u16;
+ break;
+ case HA_ALG_INTEG:
+ integ = value.u16;
+ break;
+ case HA_NONCE_I:
+ nonce_i = value.chunk;
+ break;
+ case HA_NONCE_R:
+ nonce_r = value.chunk;
+ break;
+ case HA_SECRET:
+ secret = value.chunk;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!ike_sa)
+ {
+ DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found");
+ return;
+ }
+ config = find_child_cfg(ike_sa, config_name);
+ if (!config)
+ {
+ DBG1(DBG_CHD, "HA is missing nodes child configuration");
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+
+ child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
+ ike_sa->get_other_host(ike_sa), config, 0,
+ ike_sa->has_condition(ike_sa, COND_NAT_ANY));
+ child_sa->set_mode(child_sa, mode);
+ child_sa->set_protocol(child_sa, PROTO_ESP);
+ child_sa->set_ipcomp(child_sa, ipcomp);
+
+ proposal = proposal_create(PROTO_ESP);
+ if (integ)
+ {
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
+ }
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
+ }
+ keymat = ike_sa->get_keymat(ike_sa);
+
+ if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL,
+ nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ {
+ DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
+ child_sa->destroy(child_sa);
+ proposal->destroy(proposal);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+ child_sa->set_proposal(child_sa, proposal);
+ child_sa->set_state(child_sa, CHILD_INSTALLING);
+ proposal->destroy(proposal);
+
+ /* TODO: Change CHILD_SA API to avoid cloning twice */
+ local_ts = linked_list_create();
+ remote_ts = linked_list_create();
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_LOCAL_TS:
+ local_ts->insert_last(local_ts, value.ts->clone(value.ts));
+ break;
+ case HA_REMOTE_TS:
+ remote_ts->insert_last(remote_ts, value.ts->clone(value.ts));
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (initiator)
+ {
+ if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi,
+ inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ child_sa->install(child_sa, encr_i, integ_i, outbound_spi,
+ outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ {
+ failed = TRUE;
+ }
+ }
+ else
+ {
+ if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi,
+ inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ child_sa->install(child_sa, encr_r, integ_r, outbound_spi,
+ outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ {
+ failed = TRUE;
+ }
+ }
+ chunk_clear(&encr_i);
+ chunk_clear(&integ_i);
+ chunk_clear(&encr_r);
+ chunk_clear(&integ_r);
+
+ if (failed)
+ {
+ DBG1(DBG_CHD, "HA CHILD_SA installation failed");
+ child_sa->destroy(child_sa);
+ local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
+ remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+
+ child_sa->add_policies(child_sa, local_ts, remote_ts);
+ local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
+ remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
+
+ child_sa->set_state(child_sa, CHILD_INSTALLED);
+ ike_sa->add_child_sa(ike_sa, child_sa);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+}
+
+/**
+ * Process messages of type CHILD_DELETE
+ */
+static void process_child_delete(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_INBOUND_SPI:
+ if (ike_sa)
+ {
+ ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, value.u32);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Process messages of type SEGMENT_TAKE/DROP
+ */
+static void process_segment(private_ha_dispatcher_t *this,
+ ha_message_t *message, bool take)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ if (take)
+ {
+ DBG1(DBG_CFG, "remote node takes segment %d", value.u16);
+ this->segments->deactivate(this->segments, value.u16, FALSE);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "remote node drops segment %d", value.u16);
+ this->segments->activate(this->segments, value.u16, FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Process messages of type STATUS
+ */
+static void process_status(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ segment_mask_t mask = 0;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ mask |= SEGMENTS_BIT(value.u16);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->segments->handle_status(this->segments, mask);
+}
+
+/**
+ * Process messages of type RESYNC
+ */
+static void process_resync(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ this->segments->resync(this->segments, value.u16);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Dispatcher job function
+ */
+static job_requeue_t dispatch(private_ha_dispatcher_t *this)
+{
+ ha_message_t *message;
+
+ message = this->socket->pull(this->socket);
+ switch (message->get_type(message))
+ {
+ case HA_IKE_ADD:
+ process_ike_add(this, message);
+ break;
+ case HA_IKE_UPDATE:
+ process_ike_update(this, message);
+ break;
+ case HA_IKE_DELETE:
+ process_ike_delete(this, message);
+ break;
+ case HA_CHILD_ADD:
+ process_child_add(this, message);
+ break;
+ case HA_CHILD_DELETE:
+ process_child_delete(this, message);
+ break;
+ case HA_SEGMENT_DROP:
+ process_segment(this, message, FALSE);
+ break;
+ case HA_SEGMENT_TAKE:
+ process_segment(this, message, TRUE);
+ break;
+ case HA_STATUS:
+ process_status(this, message);
+ break;
+ case HA_RESYNC:
+ process_resync(this, message);
+ break;
+ default:
+ DBG1(DBG_CFG, "received unknown HA message type %d",
+ message->get_type(message));
+ break;
+ }
+ message->destroy(message);
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implementation of ha_dispatcher_t.destroy.
+ */
+static void destroy(private_ha_dispatcher_t *this)
+{
+ this->job->cancel(this->job);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
+ ha_segments_t *segments)
+{
+ private_ha_dispatcher_t *this = malloc_thing(private_ha_dispatcher_t);
+
+ this->public.destroy = (void(*)(ha_dispatcher_t*))destroy;
+
+ this->socket = socket;
+ this->segments = segments;
+ this->job = callback_job_create((callback_job_cb_t)dispatch,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.h b/src/libcharon/plugins/ha/ha_dispatcher.h
new file mode 100644
index 000000000..d2baace3f
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_dispatcher.h
@@ -0,0 +1,50 @@
+/*
+ * 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 ha_dispatcher ha_dispatcher
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_DISPATCHER_H_
+#define HA_DISPATCHER_H_
+
+#include "ha_socket.h"
+#include "ha_segments.h"
+
+typedef struct ha_dispatcher_t ha_dispatcher_t;
+
+/**
+ * The dispatcher pulls messages in a thread an processes them.
+ */
+struct ha_dispatcher_t {
+
+ /**
+ * Destroy a ha_dispatcher_t.
+ */
+ void (*destroy)(ha_dispatcher_t *this);
+};
+
+/**
+ * Create a ha_dispatcher instance pulling from socket.
+ *
+ * @param socket socket to pull messages from
+ * @param segments segments to control based on received messages
+ * @return dispatcher object
+ */
+ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
+ ha_segments_t *segments);
+
+#endif /* HA_DISPATCHER_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
new file mode 100644
index 000000000..1f025d0e5
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+#include "ha_ike.h"
+
+typedef struct private_ha_ike_t private_ha_ike_t;
+
+/**
+ * Private data of an ha_ike_t object.
+ */
+struct private_ha_ike_t {
+
+ /**
+ * Public ha_ike_t interface.
+ */
+ ha_ike_t public;
+
+ /**
+ * socket we use for syncing
+ */
+ ha_socket_t *socket;
+
+ /**
+ * tunnel securing sync messages
+ */
+ ha_tunnel_t *tunnel;
+};
+
+/**
+ * Return condition if it is set on ike_sa
+ */
+static ike_condition_t copy_condition(ike_sa_t *ike_sa, ike_condition_t cond)
+{
+ if (ike_sa->has_condition(ike_sa, cond))
+ {
+ return cond;
+ }
+ return 0;
+}
+
+/**
+ * Return extension if it is supported by peers IKE_SA
+ */
+static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
+{
+ if (ike_sa->supports_extension(ike_sa, ext))
+ {
+ return ext;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of listener_t.ike_keys
+ */
+static bool ike_keys(private_ha_ike_t *this, ike_sa_t *ike_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey)
+{
+ ha_message_t *m;
+ chunk_t secret;
+ proposal_t *proposal;
+ u_int16_t alg, len;
+
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ { /* do not sync SA between nodes */
+ return TRUE;
+ }
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return TRUE;
+ }
+
+ m = ha_message_create(HA_IKE_ADD);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+
+ if (rekey)
+ {
+ chunk_t skd;
+ keymat_t *keymat;
+
+ keymat = rekey->get_keymat(rekey);
+ m->add_attribute(m, HA_IKE_REKEY_ID, rekey->get_id(rekey));
+ m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd));
+ m->add_attribute(m, HA_OLD_SKD, skd);
+ }
+
+ proposal = ike_sa->get_proposal(ike_sa);
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
+ {
+ m->add_attribute(m, HA_ALG_ENCR, alg);
+ if (len)
+ {
+ m->add_attribute(m, HA_ALG_ENCR_LEN, len);
+ }
+ }
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ m->add_attribute(m, HA_ALG_INTEG, alg);
+ }
+ if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ m->add_attribute(m, HA_ALG_PRF, alg);
+ }
+ m->add_attribute(m, HA_NONCE_I, nonce_i);
+ m->add_attribute(m, HA_NONCE_R, nonce_r);
+ m->add_attribute(m, HA_SECRET, secret);
+ chunk_clear(&secret);
+
+ this->socket->push(this->socket, m);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.ike_updown
+ */
+static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
+{
+ ha_message_t *m;
+
+ if (ike_sa->get_state(ike_sa) == IKE_PASSIVE)
+ { /* only sync active IKE_SAs */
+ return TRUE;
+ }
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ { /* do not sync SA between nodes */
+ return TRUE;
+ }
+
+ if (up)
+ {
+ iterator_t *iterator;
+ peer_cfg_t *peer_cfg;
+ u_int32_t extension, condition;
+ host_t *addr;
+ ike_sa_id_t *id;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ condition = copy_condition(ike_sa, COND_NAT_ANY)
+ | copy_condition(ike_sa, COND_NAT_HERE)
+ | copy_condition(ike_sa, COND_NAT_THERE)
+ | copy_condition(ike_sa, COND_NAT_FAKE)
+ | copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
+ | copy_condition(ike_sa, COND_CERTREQ_SEEN)
+ | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR);
+
+ extension = copy_extension(ike_sa, EXT_NATT)
+ | copy_extension(ike_sa, EXT_MOBIKE)
+ | copy_extension(ike_sa, EXT_HASH_AND_URL);
+
+ id = ike_sa->get_id(ike_sa);
+
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, id);
+ m->add_attribute(m, HA_LOCAL_ID, ike_sa->get_my_id(ike_sa));
+ m->add_attribute(m, HA_REMOTE_ID, ike_sa->get_other_id(ike_sa));
+ m->add_attribute(m, HA_LOCAL_ADDR, ike_sa->get_my_host(ike_sa));
+ m->add_attribute(m, HA_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
+ m->add_attribute(m, HA_CONDITIONS, condition);
+ m->add_attribute(m, HA_EXTENSIONS, extension);
+ m->add_attribute(m, HA_CONFIG_NAME, peer_cfg->get_name(peer_cfg));
+ iterator = ike_sa->create_additional_address_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&addr))
+ {
+ m->add_attribute(m, HA_ADDITIONAL_ADDR, addr);
+ }
+ iterator->destroy(iterator);
+ }
+ else
+ {
+ m = ha_message_create(HA_IKE_DELETE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ }
+ this->socket->push(this->socket, m);
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.ike_rekey
+ */
+static bool ike_rekey(private_ha_ike_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ ike_updown(this, old, FALSE);
+ ike_updown(this, new, TRUE);
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.message
+ */
+static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa,
+ message_t *message, bool incoming)
+{
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ { /* do not sync SA between nodes */
+ return TRUE;
+ }
+
+ if (message->get_exchange_type(message) != IKE_SA_INIT &&
+ message->get_request(message))
+ { /* we sync on requests, but skip it on IKE_SA_INIT */
+ ha_message_t *m;
+ u_int32_t mid;
+
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ mid = message->get_message_id(message) + 1;
+ if (incoming)
+ {
+ m->add_attribute(m, HA_RESPOND_MID, mid);
+ }
+ else
+ {
+ m->add_attribute(m, HA_INITIATE_MID, mid);
+ }
+ this->socket->push(this->socket, m);
+ }
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ message->get_exchange_type(message) == IKE_AUTH &&
+ !message->get_request(message))
+ { /* After IKE_SA has been established, sync peers virtual IP.
+ * We cannot sync it in the state_change hook, it is installed later.
+ * TODO: where to sync local VIP? */
+ ha_message_t *m;
+ host_t *vip;
+
+ vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (vip)
+ {
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_REMOTE_VIP, vip);
+ this->socket->push(this->socket, m);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of ha_ike_t.destroy.
+ */
+static void destroy(private_ha_ike_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
+{
+ private_ha_ike_t *this = malloc_thing(private_ha_ike_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
+ this->public.listener.ike_updown = (bool(*)(listener_t*,ike_sa_t *ike_sa, bool up))ike_updown;
+ this->public.listener.ike_rekey = (bool(*)(listener_t*,ike_sa_t *old, ike_sa_t *new))ike_rekey;
+ this->public.listener.message = (bool(*)(listener_t*, ike_sa_t *, message_t *,bool))message_hook;
+ this->public.destroy = (void(*)(ha_ike_t*))destroy;
+
+ this->socket = socket;
+ this->tunnel = tunnel;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_ike.h b/src/libcharon/plugins/ha/ha_ike.h
new file mode 100644
index 000000000..9de210e67
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_ike.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ha_ike ha_ike
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_IKE_H_
+#define HA_IKE_H_
+
+#include "ha_socket.h"
+#include "ha_tunnel.h"
+#include "ha_segments.h"
+
+#include <daemon.h>
+
+typedef struct ha_ike_t ha_ike_t;
+
+/**
+ * Listener to synchronize IKE_SAs.
+ */
+struct ha_ike_t {
+
+ /**
+ * Implements bus listener interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a ha_ike_t.
+ */
+ void (*destroy)(ha_ike_t *this);
+};
+
+/**
+ * Create a ha_ike instance.
+ *
+ * @param socket socket to use for sending synchronization messages
+ * @param tunnel tunnel securing sync messages, if any
+ * @return IKE listener
+ */
+ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
+
+#endif /* HA_IKE_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c
new file mode 100644
index 000000000..0ad9c22c3
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_kernel.c
@@ -0,0 +1,229 @@
+/*
+ * 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 "ha_kernel.h"
+
+typedef u_int32_t u32;
+typedef u_int8_t u8;
+
+#include <linux/jhash.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define CLUSTERIP_DIR "/proc/net/ipt_CLUSTERIP"
+
+typedef struct private_ha_kernel_t private_ha_kernel_t;
+
+/**
+ * Private data of an ha_kernel_t object.
+ */
+struct private_ha_kernel_t {
+
+ /**
+ * Public ha_kernel_t interface.
+ */
+ ha_kernel_t public;
+
+ /**
+ * Init value for jhash
+ */
+ u_int initval;
+
+ /**
+ * Total number of ClusterIP segments
+ */
+ u_int count;
+};
+
+/**
+ * Implementation of ha_kernel_t.in_segment
+ */
+static bool in_segment(private_ha_kernel_t *this, host_t *host, u_int segment)
+{
+ if (host->get_family(host) == AF_INET)
+ {
+ unsigned long hash;
+ u_int32_t addr;
+
+ addr = *(u_int32_t*)host->get_address(host).ptr;
+ hash = jhash_1word(ntohl(addr), this->initval);
+
+ if ((((u_int64_t)hash * this->count) >> 32) + 1 == segment)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Activate/Deactivate a segment for a given clusterip file
+ */
+static void enable_disable(private_ha_kernel_t *this, u_int segment,
+ char *file, bool enable)
+{
+ char cmd[8];
+ int fd;
+
+ snprintf(cmd, sizeof(cmd), "%c%d\n", enable ? '+' : '-', segment);
+
+ fd = open(file, O_WRONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_CFG, "opening CLUSTERIP file '%s' failed: %s",
+ file, strerror(errno));
+ return;
+ }
+ if (write(fd, cmd, strlen(cmd) == -1))
+ {
+ DBG1(DBG_CFG, "writing to CLUSTERIP file '%s' failed: %s",
+ file, strerror(errno));
+ }
+ close(fd);
+}
+
+/**
+ * Get the currenlty active segments in the kernel for a clusterip file
+ */
+static segment_mask_t get_active(private_ha_kernel_t *this, char *file)
+{
+ char buf[256];
+ segment_mask_t mask = 0;
+ ssize_t len;
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_CFG, "opening CLUSTERIP file '%s' failed: %s",
+ file, strerror(errno));
+ return 0;
+ }
+ len = read(fd, buf, sizeof(buf)-1);
+ if (len == -1)
+ {
+ DBG1(DBG_CFG, "reading from CLUSTERIP file '%s' failed: %s",
+ file, strerror(errno));
+ }
+ else
+ {
+ enumerator_t *enumerator;
+ u_int segment;
+ char *token;
+
+ buf[len] = '\0';
+ enumerator = enumerator_create_token(buf, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ segment = atoi(token);
+ if (segment)
+ {
+ mask |= SEGMENTS_BIT(segment);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return mask;
+}
+
+/**
+ * Implementation of ha_kernel_t.activate
+ */
+static void activate(private_ha_kernel_t *this, u_int segment)
+{
+ enumerator_t *enumerator;
+ char *file;
+
+ enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+ while (enumerator->enumerate(enumerator, NULL, &file, NULL))
+ {
+ enable_disable(this, segment, file, TRUE);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of ha_kernel_t.deactivate
+ */
+static void deactivate(private_ha_kernel_t *this, u_int segment)
+{
+ enumerator_t *enumerator;
+ char *file;
+
+ enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+ while (enumerator->enumerate(enumerator, NULL, &file, NULL))
+ {
+ enable_disable(this, segment, file, FALSE);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Disable all not-yet disabled segments on all clusterip addresses
+ */
+static void disable_all(private_ha_kernel_t *this)
+{
+ enumerator_t *enumerator;
+ segment_mask_t active;
+ char *file;
+ int i;
+
+ enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+ while (enumerator->enumerate(enumerator, NULL, &file, NULL))
+ {
+ active = get_active(this, file);
+ for (i = 1; i <= this->count; i++)
+ {
+ if (active & SEGMENTS_BIT(i))
+ {
+ enable_disable(this, i, file, FALSE);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of ha_kernel_t.destroy.
+ */
+static void destroy(private_ha_kernel_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_kernel_t *ha_kernel_create(u_int count)
+{
+ private_ha_kernel_t *this = malloc_thing(private_ha_kernel_t);
+
+ this->public.in_segment = (bool(*)(ha_kernel_t*, host_t *host, u_int segment))in_segment;
+ this->public.activate = (void(*)(ha_kernel_t*, u_int segment))activate;
+ this->public.deactivate = (void(*)(ha_kernel_t*, u_int segment))deactivate;
+ this->public.destroy = (void(*)(ha_kernel_t*))destroy;
+
+ this->initval = 0;
+ this->count = count;
+
+ disable_all(this);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_kernel.h b/src/libcharon/plugins/ha/ha_kernel.h
new file mode 100644
index 000000000..b37cc7667
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_kernel.h
@@ -0,0 +1,70 @@
+/*
+ * 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 ha_kernel ha_kernel
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_KERNEL_H_
+#define HA_KERNEL_H_
+
+typedef struct ha_kernel_t ha_kernel_t;
+
+#include "ha_segments.h"
+
+/**
+ * HA segment kernel configuration interface.
+ */
+struct ha_kernel_t {
+
+ /**
+ * Check if a host is in a segment.
+ *
+ * @param host host to check
+ * @param segment segment
+ * @return TRUE if host belongs to segment
+ */
+ bool (*in_segment)(ha_kernel_t *this, host_t *host, u_int segment);
+
+ /**
+ * Activate a segment at kernel level for all cluster addresses.
+ *
+ * @param segment segment to activate
+ */
+ void (*activate)(ha_kernel_t *this, u_int segment);
+
+ /**
+ * Deactivate a segment at kernel level for all cluster addresses.
+ *
+ * @param segment segment to deactivate
+ */
+ void (*deactivate)(ha_kernel_t *this, u_int segment);
+
+ /**
+ * Destroy a ha_kernel_t.
+ */
+ void (*destroy)(ha_kernel_t *this);
+};
+
+/**
+ * Create a ha_kernel instance.
+ *
+ * @param count total number of segments to use
+ * @param active bitmask of initially active segments
+ */
+ha_kernel_t *ha_kernel_create(u_int count);
+
+#endif /* HA_KERNEL_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c
new file mode 100644
index 000000000..54b10f05d
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_message.c
@@ -0,0 +1,663 @@
+/*
+ * 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 <arpa/inet.h>
+
+#include "ha_message.h"
+
+#include <daemon.h>
+
+#define ALLOCATION_BLOCK 64
+
+typedef struct private_ha_message_t private_ha_message_t;
+
+/**
+ * Private data of an ha_message_t object.
+ */
+struct private_ha_message_t {
+
+ /**
+ * Public ha_message_t interface.
+ */
+ ha_message_t public;
+
+ /**
+ * Allocated size of buf
+ */
+ size_t allocated;
+
+ /**
+ * Buffer containing encoded data
+ */
+ chunk_t buf;
+};
+
+typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
+
+/**
+ * Encoding if an ike_sa_id_t
+ */
+struct ike_sa_id_encoding_t {
+ u_int64_t initiator_spi;
+ u_int64_t responder_spi;
+ u_int8_t initiator;
+} __attribute__((packed));
+
+typedef struct identification_encoding_t identification_encoding_t;
+
+/**
+ * Encoding of a identification_t
+ */
+struct identification_encoding_t {
+ u_int8_t type;
+ u_int8_t len;
+ char encoding[];
+} __attribute__((packed));
+
+typedef struct host_encoding_t host_encoding_t;
+
+/**
+ * encoding of a host_t
+ */
+struct host_encoding_t {
+ u_int16_t port;
+ u_int8_t family;
+ char encoding[];
+} __attribute__((packed));
+
+typedef struct ts_encoding_t ts_encoding_t;
+
+/**
+ * encoding of a traffic_selector_t
+ */
+struct ts_encoding_t {
+ u_int8_t type;
+ u_int8_t protocol;
+ u_int16_t from_port;
+ u_int16_t to_port;
+ u_int8_t dynamic;
+ char encoding[];
+} __attribute__((packed));
+
+/**
+ * Implementation of ha_message_t.get_type
+ */
+static ha_message_type_t get_type(private_ha_message_t *this)
+{
+ return this->buf.ptr[1];
+}
+
+/**
+ * check for space in buffer, increase if necessary
+ */
+static void check_buf(private_ha_message_t *this, size_t len)
+{
+ int increased = 0;
+
+ while (this->buf.len + len > this->allocated)
+ { /* double size */
+ this->allocated += ALLOCATION_BLOCK;
+ increased++;
+ }
+ if (increased)
+ {
+ this->buf.ptr = realloc(this->buf.ptr, this->allocated);
+ }
+}
+
+/**
+ * Implementation of ha_message_t.add_attribute
+ */
+static void add_attribute(private_ha_message_t *this,
+ ha_message_attribute_t attribute, ...)
+{
+ size_t len;
+ va_list args;
+
+ check_buf(this, sizeof(u_int8_t));
+ this->buf.ptr[this->buf.len] = attribute;
+ this->buf.len += sizeof(u_int8_t);
+
+ va_start(args, attribute);
+ switch (attribute)
+ {
+ /* ike_sa_id_t* */
+ case HA_IKE_ID:
+ case HA_IKE_REKEY_ID:
+ {
+ ike_sa_id_encoding_t *enc;
+ ike_sa_id_t *id;
+
+ id = va_arg(args, ike_sa_id_t*);
+ check_buf(this, sizeof(ike_sa_id_encoding_t));
+ enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(ike_sa_id_encoding_t);
+ enc->initiator = id->is_initiator(id);
+ enc->initiator_spi = id->get_initiator_spi(id);
+ enc->responder_spi = id->get_responder_spi(id);
+ break;
+ }
+ /* identification_t* */
+ case HA_LOCAL_ID:
+ case HA_REMOTE_ID:
+ {
+ identification_encoding_t *enc;
+ identification_t *id;
+ chunk_t data;
+
+ id = va_arg(args, identification_t*);
+ data = id->get_encoding(id);
+ check_buf(this, sizeof(identification_encoding_t) + data.len);
+ enc = (identification_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(identification_encoding_t) + data.len;
+ enc->type = id->get_type(id);
+ enc->len = data.len;
+ memcpy(enc->encoding, data.ptr, data.len);
+ break;
+ }
+ /* host_t* */
+ case HA_LOCAL_ADDR:
+ case HA_REMOTE_ADDR:
+ case HA_LOCAL_VIP:
+ case HA_REMOTE_VIP:
+ case HA_ADDITIONAL_ADDR:
+ {
+ host_encoding_t *enc;
+ host_t *host;
+ chunk_t data;
+
+ host = va_arg(args, host_t*);
+ data = host->get_address(host);
+ check_buf(this, sizeof(host_encoding_t) + data.len);
+ enc = (host_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(host_encoding_t) + data.len;
+ enc->family = host->get_family(host);
+ enc->port = htons(host->get_port(host));
+ memcpy(enc->encoding, data.ptr, data.len);
+ break;
+ }
+ /* char* */
+ case HA_CONFIG_NAME:
+ {
+ char *str;
+
+ str = va_arg(args, char*);
+ len = strlen(str) + 1;
+ check_buf(this, len);
+ memcpy(this->buf.ptr + this->buf.len, str, len);
+ this->buf.len += len;
+ break;
+ }
+ /* u_int8_t */
+ case HA_IPSEC_MODE:
+ case HA_IPCOMP:
+ {
+ u_int8_t val;
+
+ val = va_arg(args, u_int);
+ check_buf(this, sizeof(val));
+ this->buf.ptr[this->buf.len] = val;
+ this->buf.len += sizeof(val);
+ break;
+ }
+ /* u_int16_t */
+ case HA_ALG_PRF:
+ case HA_ALG_OLD_PRF:
+ case HA_ALG_ENCR:
+ case HA_ALG_ENCR_LEN:
+ case HA_ALG_INTEG:
+ case HA_INBOUND_CPI:
+ case HA_OUTBOUND_CPI:
+ case HA_SEGMENT:
+ {
+ u_int16_t val;
+
+ val = va_arg(args, u_int);
+ check_buf(this, sizeof(val));
+ *(u_int16_t*)(this->buf.ptr + this->buf.len) = htons(val);
+ this->buf.len += sizeof(val);
+ break;
+ }
+ /** u_int32_t */
+ case HA_CONDITIONS:
+ case HA_EXTENSIONS:
+ case HA_INBOUND_SPI:
+ case HA_OUTBOUND_SPI:
+ case HA_INITIATE_MID:
+ case HA_RESPOND_MID:
+ {
+ u_int32_t val;
+
+ val = va_arg(args, u_int);
+ check_buf(this, sizeof(val));
+ *(u_int32_t*)(this->buf.ptr + this->buf.len) = htonl(val);
+ this->buf.len += sizeof(val);
+ break;
+ }
+ /** chunk_t */
+ case HA_NONCE_I:
+ case HA_NONCE_R:
+ case HA_SECRET:
+ case HA_OLD_SKD:
+ {
+ chunk_t chunk;
+
+ chunk = va_arg(args, chunk_t);
+ check_buf(this, chunk.len + sizeof(u_int16_t));
+ *(u_int16_t*)(this->buf.ptr + this->buf.len) = htons(chunk.len);
+ memcpy(this->buf.ptr + this->buf.len + sizeof(u_int16_t),
+ chunk.ptr, chunk.len);
+ this->buf.len += chunk.len + sizeof(u_int16_t);;
+ break;
+ }
+ /** traffic_selector_t */
+ case HA_LOCAL_TS:
+ case HA_REMOTE_TS:
+ {
+ ts_encoding_t *enc;
+ traffic_selector_t *ts;
+ chunk_t data;
+
+ ts = va_arg(args, traffic_selector_t*);
+ data = chunk_cata("cc", ts->get_from_address(ts),
+ ts->get_to_address(ts));
+ check_buf(this, sizeof(ts_encoding_t) + data.len);
+ enc = (ts_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(ts_encoding_t) + data.len;
+ enc->type = ts->get_type(ts);
+ enc->protocol = ts->get_protocol(ts);
+ enc->from_port = htons(ts->get_from_port(ts));
+ enc->to_port = htons(ts->get_to_port(ts));
+ enc->dynamic = ts->is_dynamic(ts);
+ memcpy(enc->encoding, data.ptr, data.len);
+ break;
+ }
+ default:
+ {
+ DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
+ this->buf.len -= sizeof(u_int8_t);
+ break;
+ }
+ }
+ va_end(args);
+}
+
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+ /** implementes enumerator_t */
+ enumerator_t public;
+ /** position in message */
+ chunk_t buf;
+ /** cleanup handler of current element, if any */
+ void (*cleanup)(void* data);
+ /** data to pass to cleanup handler */
+ void *cleanup_data;
+} attribute_enumerator_t;
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate
+ */
+static bool attribute_enumerate(attribute_enumerator_t *this,
+ ha_message_attribute_t *attr_out,
+ ha_message_value_t *value)
+{
+ ha_message_attribute_t attr;
+
+ if (this->cleanup)
+ {
+ this->cleanup(this->cleanup_data);
+ this->cleanup = NULL;
+ }
+ if (this->buf.len < 1)
+ {
+ return FALSE;
+ }
+ attr = this->buf.ptr[0];
+ this->buf = chunk_skip(this->buf, 1);
+ switch (attr)
+ {
+ /* ike_sa_id_t* */
+ case HA_IKE_ID:
+ case HA_IKE_REKEY_ID:
+ {
+ ike_sa_id_encoding_t *enc;
+
+ if (this->buf.len < sizeof(ike_sa_id_encoding_t))
+ {
+ return FALSE;
+ }
+ enc = (ike_sa_id_encoding_t*)(this->buf.ptr);
+ value->ike_sa_id = ike_sa_id_create(enc->initiator_spi,
+ enc->responder_spi, enc->initiator);
+ *attr_out = attr;
+ this->cleanup = (void*)value->ike_sa_id->destroy;
+ this->cleanup_data = value->ike_sa_id;
+ this->buf = chunk_skip(this->buf, sizeof(ike_sa_id_encoding_t));
+ return TRUE;
+ }
+ /* identification_t* */
+ case HA_LOCAL_ID:
+ case HA_REMOTE_ID:
+ {
+ identification_encoding_t *enc;
+
+ enc = (identification_encoding_t*)(this->buf.ptr);
+ if (this->buf.len < sizeof(identification_encoding_t) ||
+ this->buf.len < sizeof(identification_encoding_t) + enc->len)
+ {
+ return FALSE;
+ }
+ value->id = identification_create_from_encoding(enc->type,
+ chunk_create(enc->encoding, enc->len));
+ *attr_out = attr;
+ this->cleanup = (void*)value->id->destroy;
+ this->cleanup_data = value->id;
+ this->buf = chunk_skip(this->buf,
+ sizeof(identification_encoding_t) + enc->len);
+ return TRUE;
+ }
+ /* host_t* */
+ case HA_LOCAL_ADDR:
+ case HA_REMOTE_ADDR:
+ case HA_LOCAL_VIP:
+ case HA_REMOTE_VIP:
+ case HA_ADDITIONAL_ADDR:
+ {
+ host_encoding_t *enc;
+
+ enc = (host_encoding_t*)(this->buf.ptr);
+ if (this->buf.len < sizeof(host_encoding_t))
+ {
+ return FALSE;
+ }
+ value->host = host_create_from_chunk(enc->family,
+ chunk_create(enc->encoding,
+ this->buf.len - sizeof(host_encoding_t)),
+ ntohs(enc->port));
+ if (!value->host)
+ {
+ return FALSE;
+ }
+ *attr_out = attr;
+ this->cleanup = (void*)value->host->destroy;
+ this->cleanup_data = value->host;
+ this->buf = chunk_skip(this->buf, sizeof(host_encoding_t) +
+ value->host->get_address(value->host).len);
+ return TRUE;
+ }
+ /* char* */
+ case HA_CONFIG_NAME:
+ {
+ size_t len;
+
+ len = strnlen(this->buf.ptr, this->buf.len);
+ if (len >= this->buf.len)
+ {
+ return FALSE;
+ }
+ value->str = this->buf.ptr;
+ *attr_out = attr;
+ this->buf = chunk_skip(this->buf, len + 1);
+ return TRUE;
+ }
+ /* u_int8_t */
+ case HA_IPSEC_MODE:
+ case HA_IPCOMP:
+ {
+ if (this->buf.len < sizeof(u_int8_t))
+ {
+ return FALSE;
+ }
+ value->u8 = *(u_int8_t*)this->buf.ptr;
+ *attr_out = attr;
+ this->buf = chunk_skip(this->buf, sizeof(u_int8_t));
+ return TRUE;
+ }
+ /** u_int16_t */
+ case HA_ALG_PRF:
+ case HA_ALG_OLD_PRF:
+ case HA_ALG_ENCR:
+ case HA_ALG_ENCR_LEN:
+ case HA_ALG_INTEG:
+ case HA_INBOUND_CPI:
+ case HA_OUTBOUND_CPI:
+ case HA_SEGMENT:
+ {
+ if (this->buf.len < sizeof(u_int16_t))
+ {
+ return FALSE;
+ }
+ value->u16 = ntohs(*(u_int16_t*)this->buf.ptr);
+ *attr_out = attr;
+ this->buf = chunk_skip(this->buf, sizeof(u_int16_t));
+ return TRUE;
+ }
+ /** u_int32_t */
+ case HA_CONDITIONS:
+ case HA_EXTENSIONS:
+ case HA_INBOUND_SPI:
+ case HA_OUTBOUND_SPI:
+ case HA_INITIATE_MID:
+ case HA_RESPOND_MID:
+ {
+ if (this->buf.len < sizeof(u_int32_t))
+ {
+ return FALSE;
+ }
+ value->u32 = ntohl(*(u_int32_t*)this->buf.ptr);
+ *attr_out = attr;
+ this->buf = chunk_skip(this->buf, sizeof(u_int32_t));
+ return TRUE;
+ }
+ /** chunk_t */
+ case HA_NONCE_I:
+ case HA_NONCE_R:
+ case HA_SECRET:
+ case HA_OLD_SKD:
+ {
+ size_t len;
+
+ if (this->buf.len < sizeof(u_int16_t))
+ {
+ return FALSE;
+ }
+ len = ntohs(*(u_int16_t*)this->buf.ptr);
+ this->buf = chunk_skip(this->buf, sizeof(u_int16_t));
+ if (this->buf.len < len)
+ {
+ return FALSE;
+ }
+ value->chunk.len = len;
+ value->chunk.ptr = this->buf.ptr;
+ *attr_out = attr;
+ this->buf = chunk_skip(this->buf, len);
+ return TRUE;
+ }
+ case HA_LOCAL_TS:
+ case HA_REMOTE_TS:
+ {
+ ts_encoding_t *enc;
+ host_t *host;
+ int addr_len;
+
+ enc = (ts_encoding_t*)(this->buf.ptr);
+ if (this->buf.len < sizeof(ts_encoding_t))
+ {
+ return FALSE;
+ }
+ switch (enc->type)
+ {
+ case TS_IPV4_ADDR_RANGE:
+ addr_len = 4;
+ if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
+ {
+ return FALSE;
+ }
+ break;
+ case TS_IPV6_ADDR_RANGE:
+ addr_len = 16;
+ if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
+ {
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ if (enc->dynamic)
+ {
+ host = host_create_from_chunk(0,
+ chunk_create(enc->encoding, addr_len), 0);
+ if (!host)
+ {
+ return FALSE;
+ }
+ value->ts = traffic_selector_create_dynamic(enc->protocol,
+ ntohs(enc->from_port), ntohs(enc->to_port));
+ value->ts->set_address(value->ts, host);
+ host->destroy(host);
+ }
+ else
+ {
+ value->ts = traffic_selector_create_from_bytes(enc->protocol,
+ enc->type, chunk_create(enc->encoding, addr_len),
+ ntohs(enc->from_port),
+ chunk_create(enc->encoding + addr_len, addr_len),
+ ntohs(enc->to_port));
+ if (!value->ts)
+ {
+ return FALSE;
+ }
+ }
+ *attr_out = attr;
+ this->cleanup = (void*)value->ts->destroy;
+ this->cleanup_data = value->ts;
+ this->buf = chunk_skip(this->buf, sizeof(ts_encoding_t)
+ + addr_len * 2);
+ return TRUE;
+ }
+ default:
+ {
+ return FALSE;
+ }
+ }
+}
+
+/**
+ * Implementation of create_attribute_enumerator().destroy
+ */
+static void enum_destroy(attribute_enumerator_t *this)
+{
+ if (this->cleanup)
+ {
+ this->cleanup(this->cleanup_data);
+ }
+ free(this);
+}
+
+/**
+ * Implementation of ha_message_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_ha_message_t *this)
+{
+ attribute_enumerator_t *e = malloc_thing(attribute_enumerator_t);
+
+ e->public.enumerate = (void*)attribute_enumerate;
+ e->public.destroy = (void*)enum_destroy;
+
+ e->buf = chunk_skip(this->buf, 2);
+ e->cleanup = NULL;
+ e->cleanup_data = NULL;
+
+ return &e->public;
+}
+
+/**
+ * Implementation of ha_message_t.get_encoding
+ */
+static chunk_t get_encoding(private_ha_message_t *this)
+{
+ return this->buf;
+}
+
+/**
+ * Implementation of ha_message_t.destroy.
+ */
+static void destroy(private_ha_message_t *this)
+{
+ free(this->buf.ptr);
+ free(this);
+}
+
+
+static private_ha_message_t *ha_message_create_generic()
+{
+ private_ha_message_t *this = malloc_thing(private_ha_message_t);
+
+ this->public.get_type = (ha_message_type_t(*)(ha_message_t*))get_type;
+ this->public.add_attribute = (void(*)(ha_message_t*, ha_message_attribute_t attribute, ...))add_attribute;
+ this->public.create_attribute_enumerator = (enumerator_t*(*)(ha_message_t*))create_attribute_enumerator;
+ this->public.get_encoding = (chunk_t(*)(ha_message_t*))get_encoding;
+ this->public.destroy = (void(*)(ha_message_t*))destroy;
+
+ return this;
+}
+
+/**
+ * See header
+ */
+ha_message_t *ha_message_create(ha_message_type_t type)
+{
+ private_ha_message_t *this = ha_message_create_generic();
+
+ this->allocated = ALLOCATION_BLOCK;
+ this->buf.ptr = malloc(this->allocated);
+ this->buf.len = 2;
+ this->buf.ptr[0] = HA_MESSAGE_VERSION;
+ this->buf.ptr[1] = type;
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+ha_message_t *ha_message_parse(chunk_t data)
+{
+ private_ha_message_t *this;
+
+ if (data.len < 2)
+ {
+ DBG1(DBG_CFG, "HA message too short");
+ return NULL;
+ }
+ if (data.ptr[0] != HA_MESSAGE_VERSION)
+ {
+ DBG1(DBG_CFG, "HA message has version %d, expected %d",
+ data.ptr[0], HA_MESSAGE_VERSION);
+ return NULL;
+ }
+
+ this = ha_message_create_generic();
+ this->buf = chunk_clone(data);
+ this->allocated = this->buf.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h
new file mode 100644
index 000000000..b2bc23724
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_message.h
@@ -0,0 +1,205 @@
+/*
+ * 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 ha_message ha_message
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_MESSAGE_H_
+#define HA_MESSAGE_H_
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <sa/ike_sa_id.h>
+#include <selectors/traffic_selector.h>
+
+/**
+ * Protocol version of this implementation
+ */
+#define HA_MESSAGE_VERSION 1
+
+typedef struct ha_message_t ha_message_t;
+typedef enum ha_message_type_t ha_message_type_t;
+typedef enum ha_message_attribute_t ha_message_attribute_t;
+typedef union ha_message_value_t ha_message_value_t;
+
+/**
+ * Type of a HA message
+ */
+enum ha_message_type_t {
+ /** add a completely new IKE_SA */
+ HA_IKE_ADD = 1,
+ /** update an existing IKE_SA (message IDs, address update, ...) */
+ HA_IKE_UPDATE,
+ /** delete an existing IKE_SA */
+ HA_IKE_DELETE,
+ /** add a new CHILD_SA */
+ HA_CHILD_ADD,
+ /** delete an existing CHILD_SA */
+ HA_CHILD_DELETE,
+ /** segments the sending node is giving up */
+ HA_SEGMENT_DROP,
+ /** segments the sending node is taking over */
+ HA_SEGMENT_TAKE,
+ /** status with the segments the sending node is currently serving */
+ HA_STATUS,
+ /** segments the receiving node is requested to resync */
+ HA_RESYNC,
+};
+
+/**
+ * Type of attributes contained in a message
+ */
+enum ha_message_attribute_t {
+ /** ike_sa_id_t*, to identify IKE_SA */
+ HA_IKE_ID = 1,
+ /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */
+ HA_IKE_REKEY_ID,
+ /** identification_t*, local identity */
+ HA_LOCAL_ID,
+ /** identification_t*, remote identity */
+ HA_REMOTE_ID,
+ /** host_t*, local address */
+ HA_LOCAL_ADDR,
+ /** host_t*, remote address */
+ HA_REMOTE_ADDR,
+ /** char*, name of configuration */
+ HA_CONFIG_NAME,
+ /** u_int32_t, bitset of ike_condition_t */
+ HA_CONDITIONS,
+ /** u_int32_t, bitset of ike_extension_t */
+ HA_EXTENSIONS,
+ /** host_t*, local virtual IP */
+ HA_LOCAL_VIP,
+ /** host_t*, remote virtual IP */
+ HA_REMOTE_VIP,
+ /** host_t*, additional MOBIKE peer address */
+ HA_ADDITIONAL_ADDR,
+ /** chunk_t, initiators nonce */
+ HA_NONCE_I,
+ /** chunk_t, responders nonce */
+ HA_NONCE_R,
+ /** chunk_t, diffie hellman shared secret */
+ HA_SECRET,
+ /** chunk_t, SKd of old SA if rekeying */
+ HA_OLD_SKD,
+ /** u_int16_t, pseudo random function */
+ HA_ALG_PRF,
+ /** u_int16_t, old pseudo random function if rekeying */
+ HA_ALG_OLD_PRF,
+ /** u_int16_t, encryption algorithm */
+ HA_ALG_ENCR,
+ /** u_int16_t, encryption key size in bytes */
+ HA_ALG_ENCR_LEN,
+ /** u_int16_t, integrity protection algorithm */
+ HA_ALG_INTEG,
+ /** u_int8_t, IPsec mode, TUNNEL|TRANSPORT|... */
+ HA_IPSEC_MODE,
+ /** u_int8_t, IPComp protocol */
+ HA_IPCOMP,
+ /** u_int32_t, inbound security parameter index */
+ HA_INBOUND_SPI,
+ /** u_int32_t, outbound security parameter index */
+ HA_OUTBOUND_SPI,
+ /** u_int16_t, inbound security parameter index */
+ HA_INBOUND_CPI,
+ /** u_int16_t, outbound security parameter index */
+ HA_OUTBOUND_CPI,
+ /** traffic_selector_t*, local traffic selector */
+ HA_LOCAL_TS,
+ /** traffic_selector_t*, remote traffic selector */
+ HA_REMOTE_TS,
+ /** u_int32_t, initiating message ID */
+ HA_INITIATE_MID,
+ /** u_int32_t, responding message ID */
+ HA_RESPOND_MID,
+ /** u_int16_t, HA segment */
+ HA_SEGMENT,
+};
+
+/**
+ * Union to enumerate typed attributes in a message
+ */
+union ha_message_value_t {
+ u_int8_t u8;
+ u_int16_t u16;
+ u_int32_t u32;
+ char *str;
+ chunk_t chunk;
+ ike_sa_id_t *ike_sa_id;
+ identification_t *id;
+ host_t *host;
+ traffic_selector_t *ts;
+};
+
+/**
+ * Abstracted message passed between nodes in a HA cluster.
+ */
+struct ha_message_t {
+
+ /**
+ * Get the type of the message.
+ *
+ * @return message type
+ */
+ ha_message_type_t (*get_type)(ha_message_t *this);
+
+ /**
+ * Add an attribute to a message.
+ *
+ * @param attribute attribute type to add
+ * @param ... attribute specific data
+ */
+ void (*add_attribute)(ha_message_t *this,
+ ha_message_attribute_t attribute, ...);
+
+ /**
+ * Create an enumerator over all attributes in a message.
+ *
+ * @return enumerator over attribute, ha_message_value_t
+ */
+ enumerator_t* (*create_attribute_enumerator)(ha_message_t *this);
+
+ /**
+ * Get the message in a encoded form.
+ *
+ * @return chunk pointing to internal data
+ */
+ chunk_t (*get_encoding)(ha_message_t *this);
+
+ /**
+ * Destroy a ha_message_t.
+ */
+ void (*destroy)(ha_message_t *this);
+};
+
+/**
+ * Create a new ha_message instance, ready for adding attributes
+ *
+ * @param version protocol version to create a message from
+ * @param type type of the message
+ */
+ha_message_t *ha_message_create(ha_message_type_t type);
+
+/**
+ * Create a ha_message from encoded data.
+ *
+ * @param data encoded message data
+ */
+ha_message_t *ha_message_parse(chunk_t data);
+
+#endif /* HA_MESSAGE_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
new file mode 100644
index 000000000..ea255c8ab
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#include "ha_plugin.h"
+#include "ha_ike.h"
+#include "ha_child.h"
+#include "ha_socket.h"
+#include "ha_tunnel.h"
+#include "ha_dispatcher.h"
+#include "ha_segments.h"
+#include "ha_ctl.h"
+
+#include <daemon.h>
+#include <config/child_cfg.h>
+
+typedef struct private_ha_plugin_t private_ha_plugin_t;
+
+/**
+ * private data of ha plugin
+ */
+struct private_ha_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ ha_plugin_t public;
+
+ /**
+ * Communication socket
+ */
+ ha_socket_t *socket;
+
+ /**
+ * Tunnel securing sync messages.
+ */
+ ha_tunnel_t *tunnel;
+
+ /**
+ * IKE_SA synchronization
+ */
+ ha_ike_t *ike;
+
+ /**
+ * CHILD_SA synchronization
+ */
+ ha_child_t *child;
+
+ /**
+ * Dispatcher to process incoming messages
+ */
+ ha_dispatcher_t *dispatcher;
+
+ /**
+ * Active/Passive segment management
+ */
+ ha_segments_t *segments;
+
+ /**
+ * Interface to control segments at kernel level
+ */
+ ha_kernel_t *kernel;
+
+ /**
+ * Segment control interface via FIFO
+ */
+ ha_ctl_t *ctl;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_ha_plugin_t *this)
+{
+ DESTROY_IF(this->ctl);
+ charon->bus->remove_listener(charon->bus, &this->segments->listener);
+ charon->bus->remove_listener(charon->bus, &this->ike->listener);
+ charon->bus->remove_listener(charon->bus, &this->child->listener);
+ this->ike->destroy(this->ike);
+ this->child->destroy(this->child);
+ this->dispatcher->destroy(this->dispatcher);
+ this->segments->destroy(this->segments);
+ this->kernel->destroy(this->kernel);
+ this->socket->destroy(this->socket);
+ DESTROY_IF(this->tunnel);
+ free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *ha_plugin_create()
+{
+ private_ha_plugin_t *this;
+ char *local, *remote, *secret;
+ u_int count;
+ bool fifo, monitor, resync;
+
+ local = lib->settings->get_str(lib->settings,
+ "charon.plugins.ha.local", NULL);
+ remote = lib->settings->get_str(lib->settings,
+ "charon.plugins.ha.remote", NULL);
+ secret = lib->settings->get_str(lib->settings,
+ "charon.plugins.ha.secret", NULL);
+ fifo = lib->settings->get_bool(lib->settings,
+ "charon.plugins.ha.fifo_interface", TRUE);
+ monitor = lib->settings->get_bool(lib->settings,
+ "charon.plugins.ha.monitor", TRUE);
+ resync = lib->settings->get_bool(lib->settings,
+ "charon.plugins.ha.resync", TRUE);
+ count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
+ "charon.plugins.ha.segment_count", 1));
+ if (!local || !remote)
+ {
+ DBG1(DBG_CFG, "HA config misses local/remote address");
+ return NULL;
+ }
+
+ this = malloc_thing(private_ha_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+ this->tunnel = NULL;
+ this->ctl = NULL;
+
+ if (secret)
+ {
+ this->tunnel = ha_tunnel_create(local, remote, secret);
+ }
+ this->socket = ha_socket_create(local, remote);
+ if (!this->socket)
+ {
+ DESTROY_IF(this->tunnel);
+ free(this);
+ return NULL;
+ }
+ this->kernel = ha_kernel_create(count);
+ this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
+ count, strcmp(local, remote) > 0, monitor, resync);
+ if (fifo)
+ {
+ this->ctl = ha_ctl_create(this->segments);
+ }
+ this->dispatcher = ha_dispatcher_create(this->socket, this->segments);
+ this->ike = ha_ike_create(this->socket, this->tunnel);
+ this->child = ha_child_create(this->socket, this->tunnel);
+ charon->bus->add_listener(charon->bus, &this->segments->listener);
+ charon->bus->add_listener(charon->bus, &this->ike->listener);
+ charon->bus->add_listener(charon->bus, &this->child->listener);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_plugin.h b/src/libcharon/plugins/ha/ha_plugin.h
new file mode 100644
index 000000000..1ae2fe6dd
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_plugin.h
@@ -0,0 +1,47 @@
+/*
+ * 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 ha ha
+ * @ingroup cplugins
+ *
+ * @defgroup ha_plugin ha_plugin
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_PLUGIN_H_
+#define HA_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+/**
+ * UDP port we use for communication
+ */
+#define HA_PORT 4510
+
+typedef struct ha_plugin_t ha_plugin_t;
+
+/**
+ * Plugin to synchronize state in a high availability cluster.
+ */
+struct ha_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /* HA_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c
new file mode 100644
index 000000000..2199671fc
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_segments.c
@@ -0,0 +1,503 @@
+/*
+ * 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.
+ */
+
+#include "ha_segments.h"
+
+#include <pthread.h>
+
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <utils/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+#define HEARTBEAT_DELAY 1000
+#define HEARTBEAT_TIMEOUT 2100
+
+typedef struct private_ha_segments_t private_ha_segments_t;
+
+/**
+ * Private data of an ha_segments_t object.
+ */
+struct private_ha_segments_t {
+
+ /**
+ * Public ha_segments_t interface.
+ */
+ ha_segments_t public;
+
+ /**
+ * communication socket
+ */
+ ha_socket_t *socket;
+
+ /**
+ * Sync tunnel, if any
+ */
+ ha_tunnel_t *tunnel;
+
+ /**
+ * Interface to control segments at kernel level
+ */
+ ha_kernel_t *kernel;
+
+ /**
+ * Mutex to lock segment manipulation
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to wait for heartbeats
+ */
+ condvar_t *condvar;
+
+ /**
+ * Job checking for heartbeats
+ */
+ callback_job_t *job;
+
+ /**
+ * Total number of ClusterIP segments
+ */
+ u_int count;
+
+ /**
+ * mask of active segments
+ */
+ segment_mask_t active;
+
+ /**
+ * Node number
+ */
+ u_int node;
+};
+
+/**
+ * Log currently active segments
+ */
+static void log_segments(private_ha_segments_t *this, bool activated,
+ u_int segment)
+{
+ char buf[64] = "none", *pos = buf;
+ int i;
+ bool first = TRUE;
+
+ for (i = 1; i <= this->count; i++)
+ {
+ if (this->active & SEGMENTS_BIT(i))
+ {
+ if (first)
+ {
+ first = FALSE;
+ }
+ else
+ {
+ pos += snprintf(pos, buf + sizeof(buf) - pos, ",");
+ }
+ pos += snprintf(pos, buf + sizeof(buf) - pos, "%d", i);
+ }
+ }
+ DBG1(DBG_CFG, "HA segment %d %sactivated, now active: %s",
+ segment, activated ? "" : "de", buf);
+}
+
+/**
+ * Enable/Disable a specific segment
+ */
+static void enable_disable(private_ha_segments_t *this, u_int segment,
+ bool enable, bool notify)
+{
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ ike_sa_state_t old, new;
+ ha_message_t *message = NULL;
+ ha_message_type_t type;
+ bool changes = FALSE;
+
+ if (segment > this->count)
+ {
+ return;
+ }
+
+ if (enable)
+ {
+ old = IKE_PASSIVE;
+ new = IKE_ESTABLISHED;
+ type = HA_SEGMENT_TAKE;
+ if (!(this->active & SEGMENTS_BIT(segment)))
+ {
+ this->active |= SEGMENTS_BIT(segment);
+ this->kernel->activate(this->kernel, segment);
+ changes = TRUE;
+ }
+ }
+ else
+ {
+ old = IKE_ESTABLISHED;
+ new = IKE_PASSIVE;
+ type = HA_SEGMENT_DROP;
+ if (this->active & SEGMENTS_BIT(segment))
+ {
+ this->active &= ~SEGMENTS_BIT(segment);
+ this->kernel->deactivate(this->kernel, segment);
+ changes = TRUE;
+ }
+ }
+
+ if (changes)
+ {
+ enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (ike_sa->get_state(ike_sa) != old)
+ {
+ continue;
+ }
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ {
+ continue;
+ }
+ if (this->kernel->in_segment(this->kernel,
+ ike_sa->get_other_host(ike_sa), segment))
+ {
+ ike_sa->set_state(ike_sa, new);
+ }
+ }
+ enumerator->destroy(enumerator);
+ log_segments(this, enable, segment);
+ }
+
+ if (notify)
+ {
+ message = ha_message_create(type);
+ message->add_attribute(message, HA_SEGMENT, segment);
+ this->socket->push(this->socket, message);
+ }
+}
+
+/**
+ * Enable/Disable all or a specific segment, do locking
+ */
+static void enable_disable_all(private_ha_segments_t *this, u_int segment,
+ bool enable, bool notify)
+{
+ int i;
+
+ this->mutex->lock(this->mutex);
+ if (segment == 0)
+ {
+ for (i = 1; i <= this->count; i++)
+ {
+ enable_disable(this, i, enable, notify);
+ }
+ }
+ else
+ {
+ enable_disable(this, segment, enable, notify);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of ha_segments_t.activate
+ */
+static void activate(private_ha_segments_t *this, u_int segment, bool notify)
+{
+ enable_disable_all(this, segment, TRUE, notify);
+}
+
+/**
+ * Implementation of ha_segments_t.deactivate
+ */
+static void deactivate(private_ha_segments_t *this, u_int segment, bool notify)
+{
+ enable_disable_all(this, segment, FALSE, notify);
+}
+
+/**
+ * Rekey all children of an IKE_SA
+ */
+static status_t rekey_children(ike_sa_t *ike_sa)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ status_t status = SUCCESS;
+
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ DBG1(DBG_CFG, "resyncing CHILD_SA");
+ status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ if (status == DESTROY_ME)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return status;
+}
+
+/**
+ * Implementation of ha_segments_t.resync
+ */
+static void resync(private_ha_segments_t *this, u_int segment)
+{
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ ike_sa_id_t *id;
+
+ list = linked_list_create();
+ this->mutex->lock(this->mutex);
+
+ if (segment > 0 && segment <= this->count)
+ {
+ DBG1(DBG_CFG, "resyncing HA segment %d", segment);
+
+ /* we do the actual rekeying in a seperate loop to avoid rekeying
+ * an SA twice. */
+ enumerator = charon->ike_sa_manager->create_enumerator(
+ charon->ike_sa_manager);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ this->kernel->in_segment(this->kernel,
+ ike_sa->get_other_host(ike_sa), segment))
+ {
+ id = ike_sa->get_id(ike_sa);
+ list->insert_last(list, id->clone(id));
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->mutex->unlock(this->mutex);
+
+ while (list->remove_last(list, (void**)&id) == SUCCESS)
+ {
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
+ id->destroy(id);
+ if (ike_sa)
+ {
+ DBG1(DBG_CFG, "resyncing IKE_SA");
+ if (ike_sa->rekey(ike_sa) != DESTROY_ME)
+ {
+ if (rekey_children(ike_sa) != DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, ike_sa);
+ continue;
+ }
+ }
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ }
+ list->destroy(list);
+}
+
+/**
+ * Implementation of listener_t.alert
+ */
+static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa,
+ alert_t alert, va_list args)
+{
+ if (alert == ALERT_SHUTDOWN_SIGNAL)
+ {
+ deactivate(this, 0, TRUE);
+ }
+ return TRUE;
+}
+
+/**
+ * Request a resync of all segments
+ */
+static job_requeue_t request_resync(private_ha_segments_t *this)
+{
+ ha_message_t *message;
+ int i;
+
+ message = ha_message_create(HA_RESYNC);
+ for (i = 1; i <= this->count; i++)
+ {
+ message->add_attribute(message, HA_SEGMENT, i);
+ }
+ this->socket->push(this->socket, message);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Monitor heartbeat activity of remote node
+ */
+static job_requeue_t watchdog(private_ha_segments_t *this)
+{
+ int oldstate;
+ bool timeout;
+
+ this->mutex->lock(this->mutex);
+ pthread_cleanup_push((void*)this->mutex->unlock, this->mutex);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ timeout = this->condvar->timed_wait(this->condvar, this->mutex,
+ HEARTBEAT_TIMEOUT);
+ pthread_setcancelstate(oldstate, NULL);
+ pthread_cleanup_pop(TRUE);
+ if (timeout)
+ {
+ DBG1(DBG_CFG, "no heartbeat received, taking all segments");
+ activate(this, 0, TRUE);
+ /* disable heartbeat detection util we get one */
+ this->job = NULL;
+ return JOB_REQUEUE_NONE;
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Start the heartbeat detection thread
+ */
+static void start_watchdog(private_ha_segments_t *this)
+{
+ this->job = callback_job_create((callback_job_cb_t)watchdog,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+}
+
+/**
+ * Implementation of ha_segments_t.handle_status
+ */
+static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
+{
+ segment_mask_t missing;
+ int i;
+
+ this->mutex->lock(this->mutex);
+
+ missing = ~(this->active | mask);
+
+ for (i = 1; i <= this->count; i++)
+ {
+ if (missing & SEGMENTS_BIT(i))
+ {
+ if (this->node == i % 2)
+ {
+ DBG1(DBG_CFG, "HA segment %d was not handled, taking", i);
+ enable_disable(this, i, TRUE, TRUE);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "HA segment %d was not handled, dropping", i);
+ enable_disable(this, i, FALSE, TRUE);
+ }
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+ this->condvar->signal(this->condvar);
+
+ if (!this->job)
+ {
+ DBG1(DBG_CFG, "received heartbeat, reenabling watchdog");
+ start_watchdog(this);
+ }
+}
+
+/**
+ * Send a status message with our active segments
+ */
+static job_requeue_t send_status(private_ha_segments_t *this)
+{
+ ha_message_t *message;
+ int i;
+
+ message = ha_message_create(HA_STATUS);
+
+ for (i = 1; i <= this->count; i++)
+ {
+ if (this->active & SEGMENTS_BIT(i))
+ {
+ message->add_attribute(message, HA_SEGMENT, i);
+ }
+ }
+
+ this->socket->push(this->socket, message);
+
+ /* schedule next invocation */
+ charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
+ callback_job_create((callback_job_cb_t)
+ send_status, this, NULL, NULL),
+ HEARTBEAT_DELAY);
+
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of ha_segments_t.destroy.
+ */
+static void destroy(private_ha_segments_t *this)
+{
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ this->mutex->destroy(this->mutex);
+ this->condvar->destroy(this->condvar);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
+ ha_tunnel_t *tunnel, u_int count, u_int node,
+ bool monitor, bool sync)
+{
+ private_ha_segments_t *this = malloc_thing(private_ha_segments_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.alert = (bool(*)(listener_t*, ike_sa_t *, alert_t, va_list))alert_hook;
+ this->public.activate = (void(*)(ha_segments_t*, u_int segment,bool))activate;
+ this->public.deactivate = (void(*)(ha_segments_t*, u_int segment,bool))deactivate;
+ this->public.resync = (void(*)(ha_segments_t*, u_int segment))resync;
+ this->public.handle_status = (void(*)(ha_segments_t*, segment_mask_t mask))handle_status;
+ this->public.destroy = (void(*)(ha_segments_t*))destroy;
+
+ this->socket = socket;
+ this->tunnel = tunnel;
+ this->kernel = kernel;
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->count = count;
+ this->node = node;
+ this->job = NULL;
+
+ /* initially all segments are deactivated */
+ this->active = 0;
+
+ if (monitor)
+ {
+ send_status(this);
+ start_watchdog(this);
+ }
+
+ if (sync)
+ {
+ /* request a resync as soon as we are up */
+ charon->processor->queue_job(charon->processor, (job_t*)
+ callback_job_create((callback_job_cb_t)request_resync,
+ this, NULL, NULL));
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_segments.h b/src/libcharon/plugins/ha/ha_segments.h
new file mode 100644
index 000000000..6d1cd5441
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_segments.h
@@ -0,0 +1,111 @@
+/*
+ * 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 ha_segments ha_segments
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_SEGMENTS_H_
+#define HA_SEGMENTS_H_
+
+#include <daemon.h>
+
+typedef struct ha_segments_t ha_segments_t;
+
+typedef u_int16_t segment_mask_t;
+
+/**
+ * maximum number of segments
+ */
+#define SEGMENTS_MAX (sizeof(segment_mask_t)*8)
+
+/**
+ * Get the bit in the mask of a segment
+ */
+#define SEGMENTS_BIT(segment) (0x01 << (segment - 1))
+
+#include "ha_socket.h"
+#include "ha_tunnel.h"
+#include "ha_kernel.h"
+
+/**
+ * Segmentation of peers into active and passive.
+ */
+struct ha_segments_t {
+
+ /**
+ * Implements listener interface to catch daemon shutdown.
+ */
+ listener_t listener;
+
+ /**
+ * Activate a set of IKE_SAs identified by a segment.
+ *
+ * @param segment numerical segment to takeover, 0 for all
+ * @param notify wheter to notify other nodes about activation
+ */
+ void (*activate)(ha_segments_t *this, u_int segment, bool notify);
+
+ /**
+ * Deactivate a set of IKE_SAs identified by a segment.
+ *
+ * @param segment numerical segment to takeover, 0 for all
+ * @param notify wheter to notify other nodes about deactivation
+ */
+ void (*deactivate)(ha_segments_t *this, u_int segment, bool notify);
+
+ /**
+ * Resync an active segment.
+ *
+ * To reintegrade a node into the cluster, resynchronization is reqired.
+ * IKE_SAs and CHILD_SAs are synced automatically during rekeying. A call
+ * to this method enforces a rekeying immediately sync all state of a
+ * segment.
+ *
+ * @param segment segment to resync
+ */
+ void (*resync)(ha_segments_t *this, u_int segment);
+
+ /**
+ * Handle a status message from the remote node.
+ *
+ * @param mask segments the remote node is serving actively
+ */
+ void (*handle_status)(ha_segments_t *this, segment_mask_t mask);
+
+ /**
+ * Destroy a ha_segments_t.
+ */
+ void (*destroy)(ha_segments_t *this);
+};
+
+/**
+ * Create a ha_segments instance.
+ *
+ * @param socket socket to communicate segment (de-)activation
+ * @param kernel interface to control segments at kernel level
+ * @param tunnel HA tunnel
+ * @param count number of segments the cluster uses
+ * @param node node, currently 1 or 0
+ * @param monitor should we use monitoring functionality
+ * @param resync request a complete resync on startup
+ * @return segment object
+ */
+ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
+ ha_tunnel_t *tunnel, u_int count, u_int node,
+ bool monitor, bool resync);
+
+#endif /* HA_SEGMENTS_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c
new file mode 100644
index 000000000..b84b02868
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_socket.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2008-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 "ha_socket.h"
+#include "ha_plugin.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ha_socket_t private_ha_socket_t;
+
+/**
+ * Private data of an ha_socket_t object.
+ */
+struct private_ha_socket_t {
+
+ /**
+ * Public ha_socket_t interface.
+ */
+ ha_socket_t public;
+
+ /**
+ * UDP communication socket fd
+ */
+ int fd;
+
+ /**
+ * local host to receive/send from
+ */
+ host_t *local;
+
+ /**
+ * remote host to receive/send to
+ */
+ host_t *remote;
+};
+
+/**
+ * Data to pass to the send_message() callback job
+ */
+typedef struct {
+ ha_message_t *message;
+ private_ha_socket_t *this;
+} job_data_t;
+
+/**
+ * Cleanup job data
+ */
+static void job_data_destroy(job_data_t *this)
+{
+ this->message->destroy(this->message);
+ free(this);
+}
+
+/**
+ * Callback to asynchronously send messages
+ */
+static job_requeue_t send_message(job_data_t *data)
+{
+ private_ha_socket_t *this;
+ chunk_t chunk;
+
+ this = data->this;
+ chunk = data->message->get_encoding(data->message);
+ if (send(this->fd, chunk.ptr, chunk.len, 0) < chunk.len)
+ {
+ DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of ha_socket_t.push
+ */
+static void push(private_ha_socket_t *this, ha_message_t *message)
+{
+ chunk_t chunk;
+
+ /* Try to send synchronously, but non-blocking. */
+ chunk = message->get_encoding(message);
+ if (send(this->fd, chunk.ptr, chunk.len, MSG_DONTWAIT) < chunk.len)
+ {
+ if (errno == EAGAIN)
+ {
+ callback_job_t *job;
+ job_data_t *data;
+
+ /* Fallback to asynchronous transmission. This is required, as sendto()
+ * is a blocking call if it acquires a policy. We could end up in a
+ * deadlock, as we own an IKE_SA. */
+ data = malloc_thing(job_data_t);
+ data->message = message;
+ data->this = this;
+
+ job = callback_job_create((callback_job_cb_t)send_message,
+ data, (void*)job_data_destroy, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)job);
+ return;
+ }
+ DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
+ }
+ message->destroy(message);
+}
+
+/**
+ * Implementation of ha_socket_t.pull
+ */
+static ha_message_t *pull(private_ha_socket_t *this)
+{
+ while (TRUE)
+ {
+ ha_message_t *message;
+ char buf[1024];
+ int oldstate;
+ ssize_t len;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ len = recv(this->fd, buf, sizeof(buf), 0);
+ pthread_setcancelstate(oldstate, NULL);
+ if (len <= 0)
+ {
+ switch (errno)
+ {
+ case ECONNREFUSED:
+ case EINTR:
+ continue;
+ default:
+ DBG1(DBG_CFG, "pulling HA message failed: %s",
+ strerror(errno));
+ sleep(1);
+ }
+ }
+ message = ha_message_parse(chunk_create(buf, len));
+ if (message)
+ {
+ return message;
+ }
+ }
+}
+
+/**
+ * Open and connect the HA socket
+ */
+static bool open_socket(private_ha_socket_t *this)
+{
+ this->fd = socket(this->local->get_family(this->local), SOCK_DGRAM, 0);
+ if (this->fd == -1)
+ {
+ DBG1(DBG_CFG, "opening HA socket failed: %s", strerror(errno));
+ return FALSE;
+ }
+
+ if (bind(this->fd, this->local->get_sockaddr(this->local),
+ *this->local->get_sockaddr_len(this->local)) == -1)
+ {
+ DBG1(DBG_CFG, "binding HA socket failed: %s", strerror(errno));
+ close(this->fd);
+ this->fd = -1;
+ return FALSE;
+ }
+ if (connect(this->fd, this->remote->get_sockaddr(this->remote),
+ *this->remote->get_sockaddr_len(this->remote)) == -1)
+ {
+ DBG1(DBG_CFG, "connecting HA socket failed: %s", strerror(errno));
+ close(this->fd);
+ this->fd = -1;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Implementation of ha_socket_t.destroy.
+ */
+static void destroy(private_ha_socket_t *this)
+{
+ if (this->fd != -1)
+ {
+ close(this->fd);
+ }
+ DESTROY_IF(this->local);
+ DESTROY_IF(this->remote);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_socket_t *ha_socket_create(char *local, char *remote)
+{
+ private_ha_socket_t *this = malloc_thing(private_ha_socket_t);
+
+ this->public.push = (void(*)(ha_socket_t*, ha_message_t*))push;
+ this->public.pull = (ha_message_t*(*)(ha_socket_t*))pull;
+ this->public.destroy = (void(*)(ha_socket_t*))destroy;
+
+ this->local = host_create_from_dns(local, 0, HA_PORT);
+ this->remote = host_create_from_dns(remote, 0, HA_PORT);
+ this->fd = -1;
+
+ if (!this->local || !this->remote)
+ {
+ DBG1(DBG_CFG, "invalid local/remote HA address");
+ destroy(this);
+ return NULL;
+ }
+ if (!open_socket(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_socket.h b/src/libcharon/plugins/ha/ha_socket.h
new file mode 100644
index 000000000..8d398e22b
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_socket.h
@@ -0,0 +1,60 @@
+/*
+ * 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 ha_socket ha_socket
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_SOCKET_H_
+#define HA_SOCKET_H_
+
+#include "ha_message.h"
+
+#include <sa/ike_sa.h>
+
+typedef struct ha_socket_t ha_socket_t;
+
+/**
+ * Socket to send/received SA synchronization data
+ */
+struct ha_socket_t {
+
+ /**
+ * Push synchronization information to the responsible node.
+ *
+ * @param message message to send, gets destroyed by push()
+ */
+ void (*push)(ha_socket_t *this, ha_message_t *message);
+
+ /**
+ * Pull synchronization information from a peer we are responsible.
+ *
+ * @return received message
+ */
+ ha_message_t *(*pull)(ha_socket_t *this);
+
+ /**
+ * Destroy a ha_socket_t.
+ */
+ void (*destroy)(ha_socket_t *this);
+};
+
+/**
+ * Create a ha_socket instance.
+ */
+ha_socket_t *ha_socket_create(char *local, char *remote);
+
+#endif /* HA_SOCKET_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
new file mode 100644
index 000000000..b3511e5f0
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -0,0 +1,298 @@
+/*
+ * 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 "ha_tunnel.h"
+#include "ha_plugin.h"
+
+#include <daemon.h>
+#include <utils/identification.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ha_tunnel_t private_ha_tunnel_t;
+typedef struct ha_backend_t ha_backend_t;
+typedef struct ha_creds_t ha_creds_t;
+
+/**
+ * Serves credentials for the HA SA
+ */
+struct ha_creds_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t public;
+
+ /**
+ * own identity
+ */
+ identification_t *local;
+
+ /**
+ * peer identity
+ */
+ identification_t *remote;
+
+ /**
+ * Shared key to serve
+ */
+ shared_key_t *key;
+};
+
+/**
+ * Serves configurations for the HA SA
+ */
+struct ha_backend_t {
+
+ /**
+ * Implements backend_t
+ */
+ backend_t public;
+
+ /**
+ * peer config we serve
+ */
+ peer_cfg_t *cfg;
+};
+
+/**
+ * Private data of an ha_tunnel_t object.
+ */
+struct private_ha_tunnel_t {
+
+ /**
+ * Public ha_tunnel_t interface.
+ */
+ ha_tunnel_t public;
+
+ /**
+ * Reqid of installed trap
+ */
+ u_int32_t trap;
+
+ /**
+ * backend for HA SA
+ */
+ ha_backend_t backend;
+
+ /**
+ * credential set for HA SA
+ */
+ ha_creds_t creds;
+};
+
+/**
+ * Implementation of ha_tunnel_t.is_sa
+ */
+static bool is_sa(private_ha_tunnel_t *this, ike_sa_t *ike_sa)
+{
+ peer_cfg_t *cfg = this->backend.cfg;
+
+ return cfg && ike_sa->get_ike_cfg(ike_sa) == cfg->get_ike_cfg(cfg);
+}
+
+/**
+ * Enumerator over HA shared_key
+ */
+typedef struct {
+ /** Implements enumerator_t */
+ enumerator_t public;
+ /** a single secret we serve */
+ shared_key_t *key;
+} shared_enum_t;
+
+/**
+ * Implementation of shared_enum_t.enumerate
+ */
+static bool shared_enumerate(shared_enum_t *this, shared_key_t **key,
+ id_match_t *me, id_match_t *other)
+{
+ if (this->key)
+ {
+ if (me)
+ {
+ *me = ID_MATCH_PERFECT;
+ }
+ if (other)
+ {
+ *other = ID_MATCH_PERFECT;
+ }
+ *key = this->key;
+ this->key = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implements ha_creds_t.create_shared_enumerator
+ */
+static enumerator_t* create_shared_enumerator(ha_creds_t *this,
+ shared_key_type_t type, identification_t *me,
+ identification_t *other)
+{
+ shared_enum_t *enumerator;
+
+ if (type != SHARED_IKE && type != SHARED_ANY)
+ {
+ return NULL;
+ }
+ if (me && !me->equals(me, this->local))
+ {
+ return NULL;
+ }
+ if (other && !other->equals(other, this->remote))
+ {
+ return NULL;
+ }
+
+ enumerator = malloc_thing(shared_enum_t);
+ enumerator->public.enumerate = (void*)shared_enumerate;
+ enumerator->public.destroy = (void*)free;
+ enumerator->key = this->key;
+
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(ha_backend_t *this,
+ identification_t *me, identification_t *other)
+{
+ return enumerator_create_single(this->cfg, NULL);
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(ha_backend_t *this,
+ host_t *me, host_t *other)
+{
+ return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL);
+}
+
+/**
+ * Install configs and a a trap for secured HA message exchange
+ */
+static void setup_tunnel(private_ha_tunnel_t *this,
+ char *local, char *remote, char *secret)
+{
+ peer_cfg_t *peer_cfg;
+ ike_cfg_t *ike_cfg;
+ auth_cfg_t *auth_cfg;
+ child_cfg_t *child_cfg;
+ traffic_selector_t *ts;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = 21600, .rekey = 20400, .jitter = 400,
+ },
+ };
+
+ /* setup credentials */
+ this->creds.local = identification_create_from_string(local);
+ this->creds.remote = identification_create_from_string(remote);
+ this->creds.key = shared_key_create(SHARED_IKE,
+ chunk_clone(chunk_create(secret, strlen(secret))));
+ this->creds.public.create_private_enumerator = (void*)return_null;
+ this->creds.public.create_cert_enumerator = (void*)return_null;
+ this->creds.public.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->creds.public.create_cdp_enumerator = (void*)return_null;
+ this->creds.public.cache_cert = (void*)nop;
+
+ charon->credentials->add_set(charon->credentials, &this->creds.public);
+
+ /* create config and backend */
+ ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT,
+ remote, IKEV2_UDP_PORT);
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ peer_cfg = peer_cfg_create("ha", 2, ike_cfg, CERT_NEVER_SEND,
+ UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30,
+ NULL, NULL, FALSE, NULL, NULL);
+
+ auth_cfg = auth_cfg_create();
+ auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY,
+ identification_create_from_string(local));
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+
+ auth_cfg = auth_cfg_create();
+ auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY,
+ identification_create_from_string(remote));
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+
+ child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE,
+ MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
+ child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+ ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+ ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
+ child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+ 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));
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+
+ this->backend.cfg = peer_cfg;
+ this->backend.public.create_peer_cfg_enumerator = (void*)create_peer_cfg_enumerator;
+ this->backend.public.create_ike_cfg_enumerator = (void*)create_ike_cfg_enumerator;
+ this->backend.public.get_peer_cfg_by_name = (void*)return_null;
+
+ charon->backends->add_backend(charon->backends, &this->backend.public);
+
+ /* install an acquiring trap */
+ this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg);
+}
+
+/**
+ * Implementation of ha_tunnel_t.destroy.
+ */
+static void destroy(private_ha_tunnel_t *this)
+{
+ if (this->backend.cfg)
+ {
+ charon->backends->remove_backend(charon->backends, &this->backend.public);
+ this->backend.cfg->destroy(this->backend.cfg);
+ }
+ if (this->creds.key)
+ {
+ charon->credentials->remove_set(charon->credentials, &this->creds.public);
+ this->creds.key->destroy(this->creds.key);
+ }
+ this->creds.local->destroy(this->creds.local);
+ this->creds.remote->destroy(this->creds.remote);
+ if (this->trap)
+ {
+ charon->traps->uninstall(charon->traps, this->trap);
+ }
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret)
+{
+ private_ha_tunnel_t *this = malloc_thing(private_ha_tunnel_t);
+
+ this->public.is_sa = (bool(*)(ha_tunnel_t*, ike_sa_t *ike_sa))is_sa;
+ this->public.destroy = (void(*)(ha_tunnel_t*))destroy;
+
+ setup_tunnel(this, local, remote, secret);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/ha/ha_tunnel.h b/src/libcharon/plugins/ha/ha_tunnel.h
new file mode 100644
index 000000000..085fb6122
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_tunnel.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ha_ ha_tunnel
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_TUNNEL_H_
+#define HA_TUNNEL_H_
+
+#include <sa/ike_sa.h>
+
+typedef struct ha_tunnel_t ha_tunnel_t;
+
+/**
+ * Socket to send/received SA synchronization data
+ */
+struct ha_tunnel_t {
+
+ /**
+ * Check if an IKE_SA is used for exchanging HA messages.
+ *
+ * @param ike_Sa ike_sa to check
+ * @return TRUE if IKE_SA is used to secure HA messages
+ */
+ bool (*is_sa)(ha_tunnel_t *this, ike_sa_t *ike_sa);
+
+ /**
+ * Destroy a ha_tunnel_t.
+ */
+ void (*destroy)(ha_tunnel_t *this);
+};
+
+/**
+ * Create a ha_tunnel instance.
+ *
+ * @param local local address of HA tunnel
+ * @param remote remote address of HA tunnel
+ * @param secret PSK tunnel authentication secret
+ * @return HA tunnel instance
+ */
+ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret);
+
+#endif /* HA_TUNNEL_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_klips/Makefile.am b/src/libcharon/plugins/kernel_klips/Makefile.am
new file mode 100644
index 000000000..540bbe106
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+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/libcharon/plugins/kernel_klips/Makefile.in b/src/libcharon/plugins/kernel_klips/Makefile.in
new file mode 100644
index 000000000..f0d112a0f
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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_klips
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__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)
+libstrongswan_kernel_klips_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_klips_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_klips_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_klips_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_klips_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_klips_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-klips.la
+@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/libcharon/plugins/kernel_klips/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-klips.la: $(libstrongswan_kernel_klips_la_OBJECTS) $(libstrongswan_kernel_klips_la_DEPENDENCIES)
+ $(libstrongswan_kernel_klips_la_LINK) $(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
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_klips_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_klips_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
new file mode 100644
index 000000000..01df4f71a
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -0,0 +1,2657 @@
+/*
+ * 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 <daemon.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
+
+/** default timeout for generated SPIs (in seconds) */
+#define SPI_TIMEOUT 30
+
+/** buffer size for PF_KEY messages */
+#define PFKEY_BUFFER_SIZE 2048
+
+/** PF_KEY messages are 64 bit aligned */
+#define PFKEY_ALIGNMENT 8
+/** aligns len to 64 bits */
+#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1))
+/** calculates the properly padded length in 64 bit chunks */
+#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT))
+/** calculates user mode length i.e. in bytes */
+#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT)
+
+/** given a PF_KEY message header and an extension this updates the length in the header */
+#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len)
+/** given a PF_KEY message header this returns a pointer to the next extension */
+#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len)))
+/** copy an extension and append it to a PF_KEY message */
+#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))))
+/** given a PF_KEY extension this returns a pointer to the next extension */
+#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))
+/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */
+#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext))
+/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */
+#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len <= (len))
+
+/** special SPI values used for policies in KLIPS */
+#define SPI_PASS 256
+#define SPI_DROP 257
+#define SPI_REJECT 258
+#define SPI_HOLD 259
+#define SPI_TRAP 260
+#define SPI_TRAPSUBNET 261
+
+/** the prefix of the name of KLIPS ipsec devices */
+#define IPSEC_DEV_PREFIX "ipsec"
+/** this is the default number of ipsec devices */
+#define DEFAULT_IPSEC_DEV_COUNT 4
+/** TRUE if the given name matches an ipsec device */
+#define IS_IPSEC_DEV(name) (strneq((name), IPSEC_DEV_PREFIX, sizeof(IPSEC_DEV_PREFIX) - 1))
+
+/** the following stuff is from ipsec_tunnel.h */
+struct ipsectunnelconf
+{
+ __u32 cf_cmd;
+ union
+ {
+ char cfu_name[12];
+ } cf_u;
+#define cf_name cf_u.cfu_name
+};
+
+#define IPSEC_SET_DEV (SIOCDEVPRIVATE)
+#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1)
+#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2)
+
+typedef struct private_kernel_klips_ipsec_t private_kernel_klips_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_klips class.
+ */
+struct private_kernel_klips_ipsec_t
+{
+ /**
+ * Public part of the kernel_klips_t object.
+ */
+ kernel_klips_ipsec_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * List of installed policies (policy_entry_t)
+ */
+ linked_list_t *policies;
+
+ /**
+ * List of allocated SPIs without installed SA (sa_entry_t)
+ */
+ linked_list_t *allocated_spis;
+
+ /**
+ * List of installed SAs (sa_entry_t)
+ */
+ linked_list_t *installed_sas;
+
+ /**
+ * whether to install routes along policies
+ */
+ bool install_routes;
+
+ /**
+ * List of ipsec devices (ipsec_dev_t)
+ */
+ linked_list_t *ipsec_devices;
+
+ /**
+ * job receiving PF_KEY events
+ */
+ callback_job_t *job;
+
+ /**
+ * mutex to lock access to the PF_KEY socket
+ */
+ mutex_t *mutex_pfkey;
+
+ /**
+ * PF_KEY socket to communicate with the kernel
+ */
+ int socket;
+
+ /**
+ * PF_KEY socket to receive acquire and expire events
+ */
+ int socket_events;
+
+ /**
+ * sequence number for messages sent to the kernel
+ */
+ int seq;
+
+};
+
+
+typedef struct ipsec_dev_t ipsec_dev_t;
+
+/**
+ * ipsec device
+ */
+struct ipsec_dev_t {
+ /** name of the virtual ipsec interface */
+ char name[IFNAMSIZ];
+
+ /** name of the physical interface */
+ char phys_name[IFNAMSIZ];
+
+ /** by how many CHILD_SA's this ipsec device is used */
+ u_int refcount;
+};
+
+/**
+ * compare the given name with the virtual device name
+ */
+static inline bool ipsec_dev_match_byname(ipsec_dev_t *current, char *name)
+{
+ return name && streq(current->name, name);
+}
+
+/**
+ * compare the given name with the physical device name
+ */
+static inline bool ipsec_dev_match_byphys(ipsec_dev_t *current, char *name)
+{
+ return name && streq(current->phys_name, name);
+}
+
+/**
+ * matches free ipsec devices
+ */
+static inline bool ipsec_dev_match_free(ipsec_dev_t *current)
+{
+ return current->refcount == 0;
+}
+
+/**
+ * tries to find an ipsec_dev_t object by name
+ */
+static status_t find_ipsec_dev(private_kernel_klips_ipsec_t *this, char *name,
+ ipsec_dev_t **dev)
+{
+ linked_list_match_t match = (linked_list_match_t)(IS_IPSEC_DEV(name) ?
+ ipsec_dev_match_byname : ipsec_dev_match_byphys);
+ return this->ipsec_devices->find_first(this->ipsec_devices, match,
+ (void**)dev, name);
+}
+
+/**
+ * attach an ipsec device to a physical interface
+ */
+static status_t attach_ipsec_dev(char* name, char *phys_name)
+{
+ int sock;
+ struct ifreq req;
+ struct ipsectunnelconf *itc = (struct ipsectunnelconf*)&req.ifr_data;
+ short phys_flags;
+ int mtu;
+
+ DBG2(DBG_KNL, "attaching virtual interface %s to %s", name, phys_name);
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
+ {
+ return FAILED;
+ }
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+ phys_flags = req.ifr_flags;
+
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+
+ if (req.ifr_flags & IFF_UP)
+ {
+ /* if it's already up, it is already attached, detach it first */
+ ioctl(sock, IPSEC_DEL_DEV, &req);
+ }
+
+ /* attach it */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ strncpy(itc->cf_name, phys_name, sizeof(itc->cf_name));
+ ioctl(sock, IPSEC_SET_DEV, &req);
+
+ /* copy address from physical to virtual */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFADDR, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFADDR, &req);
+ }
+
+ /* copy net mask from physical to virtual */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFNETMASK, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFNETMASK, &req);
+ }
+
+ /* copy other flags and addresses */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
+ {
+ if (phys_flags & IFF_POINTOPOINT)
+ {
+ req.ifr_flags |= IFF_POINTOPOINT;
+ req.ifr_flags &= ~IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFDSTADDR, &req);
+ }
+ }
+ else if (phys_flags & IFF_BROADCAST)
+ {
+ req.ifr_flags &= ~IFF_POINTOPOINT;
+ req.ifr_flags |= IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFBRDADDR, &req)==0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFBRDADDR, &req);
+ }
+ }
+ else
+ {
+ req.ifr_flags &= ~IFF_POINTOPOINT;
+ req.ifr_flags &= ~IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+ }
+
+ mtu = lib->settings->get_int(lib->settings,
+ "charon.plugins.kernel-klips.ipsec_dev_mtu", 0);
+ if (mtu <= 0)
+ {
+ /* guess MTU as physical MTU - ESP overhead [- NAT-T overhead]
+ * ESP overhead : 73 bytes
+ * NAT-T overhead : 8 bytes ==> 81 bytes
+ *
+ * assuming tunnel mode with AES encryption and integrity
+ * outer IP header : 20 bytes
+ * (NAT-T UDP header: 8 bytes)
+ * ESP header : 8 bytes
+ * IV : 16 bytes
+ * padding : 15 bytes (worst-case)
+ * pad len / NH : 2 bytes
+ * auth data : 12 bytes
+ */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ ioctl(sock, SIOCGIFMTU, &req);
+ mtu = req.ifr_mtu - 81;
+ }
+
+ /* set MTU */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ req.ifr_mtu = mtu;
+ ioctl(sock, SIOCSIFMTU, &req);
+
+ /* bring ipsec device UP */
+ if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
+ {
+ req.ifr_flags |= IFF_UP;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+
+ close(sock);
+ return SUCCESS;
+}
+
+/**
+ * detach an ipsec device from a physical interface
+ */
+static status_t detach_ipsec_dev(char* name, char *phys_name)
+{
+ int sock;
+ struct ifreq req;
+
+ DBG2(DBG_KNL, "detaching virtual interface %s from %s", name,
+ strlen(phys_name) ? phys_name : "any physical interface");
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
+ {
+ return FAILED;
+ }
+
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+
+ /* shutting interface down */
+ if (req.ifr_flags & IFF_UP)
+ {
+ req.ifr_flags &= ~IFF_UP;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+
+ /* unset address */
+ memset(&req.ifr_addr, 0, sizeof(req.ifr_addr));
+ req.ifr_addr.sa_family = AF_INET;
+ ioctl(sock, SIOCSIFADDR, &req);
+
+ /* detach interface */
+ ioctl(sock, IPSEC_DEL_DEV, &req);
+
+ close(sock);
+ return SUCCESS;
+}
+
+/**
+ * destroy an ipsec_dev_t object
+ */
+static void ipsec_dev_destroy(ipsec_dev_t *this)
+{
+ detach_ipsec_dev(this->name, this->phys_name);
+ free(this);
+}
+
+
+typedef struct route_entry_t route_entry_t;
+
+/**
+ * installed routing entry
+ */
+struct route_entry_t {
+ /** Name of the interface the route is bound to */
+ char *if_name;
+
+ /** Source ip of the route */
+ host_t *src_ip;
+
+ /** Gateway for this route */
+ host_t *gateway;
+
+ /** Destination net */
+ chunk_t dst_net;
+
+ /** Destination net prefixlen */
+ u_int8_t prefixlen;
+};
+
+/**
+ * destroy an route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+ free(this->if_name);
+ this->src_ip->destroy(this->src_ip);
+ this->gateway->destroy(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+
+ /** reqid of this policy, if setup as trap */
+ u_int32_t reqid;
+
+ /** direction of this policy: in, out, forward */
+ u_int8_t direction;
+
+ /** parameters of installed policy */
+ struct {
+ /** subnet and port */
+ host_t *net;
+ /** subnet mask */
+ u_int8_t mask;
+ /** protocol */
+ u_int8_t proto;
+ } src, dst;
+
+ /** associated route installed for this policy */
+ route_entry_t *route;
+
+ /** by how many CHILD_SA's this policy is actively used */
+ u_int activecount;
+
+ /** by how many CHILD_SA's this policy is trapped */
+ u_int trapcount;
+};
+
+/**
+ * convert a numerical netmask to a host_t
+ */
+static host_t *mask2host(int family, u_int8_t mask)
+{
+ static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+ chunk_t chunk = chunk_alloca(family == AF_INET ? 4 : 16);
+ int bytes = mask / 8, bits = mask % 8;
+ memset(chunk.ptr, 0xFF, bytes);
+ memset(chunk.ptr + bytes, 0, chunk.len - bytes);
+ if (bits)
+ {
+ chunk.ptr[bytes] = bitmask[bits];
+ }
+ return host_create_from_chunk(family, chunk, 0);
+}
+
+/**
+ * check if a host is in a subnet (host with netmask in bits)
+ */
+static bool is_host_in_net(host_t *host, host_t *net, u_int8_t mask)
+{
+ static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+ chunk_t host_chunk, net_chunk;
+ int bytes = mask / 8, bits = mask % 8;
+
+ host_chunk = host->get_address(host);
+ net_chunk = net->get_address(net);
+
+ if (host_chunk.len != net_chunk.len)
+ {
+ return FALSE;
+ }
+
+ if (memeq(host_chunk.ptr, net_chunk.ptr, bytes))
+ {
+ return (bits == 0) ||
+ (host_chunk.ptr[bytes] & bitmask[bits]) ==
+ (net_chunk.ptr[bytes] & bitmask[bits]);
+ }
+
+ return FALSE;
+}
+
+/**
+ * create a policy_entry_t object
+ */
+static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t dir)
+{
+ policy_entry_t *policy = malloc_thing(policy_entry_t);
+ policy->reqid = 0;
+ policy->direction = dir;
+ policy->route = NULL;
+ policy->activecount = 0;
+ policy->trapcount = 0;
+
+ src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
+ dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
+
+ /* src or dest proto may be "any" (0), use more restrictive one */
+ policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+ policy->src.proto = policy->src.proto ? policy->src.proto : 0;
+ policy->dst.proto = policy->src.proto;
+
+ return policy;
+}
+
+/**
+ * destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(policy_entry_t *this)
+{
+ DESTROY_IF(this->src.net);
+ DESTROY_IF(this->dst.net);
+ if (this->route)
+ {
+ route_entry_destroy(this->route);
+ }
+ free(this);
+}
+
+/**
+ * compares two policy_entry_t
+ */
+static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy)
+{
+ return current->direction == policy->direction &&
+ current->src.proto == policy->src.proto &&
+ current->dst.proto == policy->dst.proto &&
+ current->src.mask == policy->src.mask &&
+ current->dst.mask == policy->dst.mask &&
+ current->src.net->equals(current->src.net, policy->src.net) &&
+ current->dst.net->equals(current->dst.net, policy->dst.net);
+}
+
+static inline bool policy_entry_match_byaddrs(policy_entry_t *current, host_t *src,
+ host_t *dst)
+{
+ return is_host_in_net(src, current->src.net, current->src.mask) &&
+ is_host_in_net(dst, current->dst.net, current->dst.mask);
+}
+
+typedef struct sa_entry_t sa_entry_t;
+
+/**
+ * used for two things:
+ * - allocated SPIs that have not yet resulted in an installed SA
+ * - installed inbound SAs with enabled UDP encapsulation
+ */
+struct sa_entry_t {
+
+ /** protocol of this SA */
+ protocol_id_t protocol;
+
+ /** reqid of this SA */
+ u_int32_t reqid;
+
+ /** SPI of this SA */
+ u_int32_t spi;
+
+ /** src address of this SA */
+ host_t *src;
+
+ /** dst address of this SA */
+ host_t *dst;
+
+ /** TRUE if this SA uses UDP encapsulation */
+ bool encap;
+
+ /** TRUE if this SA is inbound */
+ bool inbound;
+};
+
+/**
+ * create an sa_entry_t object
+ */
+static sa_entry_t *create_sa_entry(protocol_id_t protocol, u_int32_t spi,
+ u_int32_t reqid, host_t *src, host_t *dst,
+ bool encap, bool inbound)
+{
+ sa_entry_t *sa = malloc_thing(sa_entry_t);
+ sa->protocol = protocol;
+ sa->reqid = reqid;
+ sa->spi = spi;
+ sa->src = src ? src->clone(src) : NULL;
+ sa->dst = dst ? dst->clone(dst) : NULL;
+ sa->encap = encap;
+ sa->inbound = inbound;
+ return sa;
+}
+
+/**
+ * destroy an sa_entry_t object
+ */
+static void sa_entry_destroy(sa_entry_t *this)
+{
+ DESTROY_IF(this->src);
+ DESTROY_IF(this->dst);
+ free(this);
+}
+
+/**
+ * match an sa_entry_t for an inbound SA that uses UDP encapsulation by spi and src (remote) address
+ */
+static inline bool sa_entry_match_encapbysrc(sa_entry_t *current, u_int32_t *spi,
+ host_t *src)
+{
+ return current->encap && current->inbound &&
+ current->spi == *spi && src->ip_equals(src, current->src);
+}
+
+/**
+ * match an sa_entry_t by protocol, spi and dst address (as the kernel does it)
+ */
+static inline bool sa_entry_match_bydst(sa_entry_t *current, protocol_id_t *protocol,
+ u_int32_t *spi, host_t *dst)
+{
+ return current->protocol == *protocol && current->spi == *spi && dst->ip_equals(dst, current->dst);
+}
+
+/**
+ * match an sa_entry_t by protocol, reqid and spi
+ */
+static inline bool sa_entry_match_byid(sa_entry_t *current, protocol_id_t *protocol,
+ u_int32_t *spi, u_int32_t *reqid)
+{
+ return current->protocol == *protocol && current->spi == *spi && current->reqid == *reqid;
+}
+
+typedef struct pfkey_msg_t pfkey_msg_t;
+
+struct pfkey_msg_t
+{
+ /**
+ * PF_KEY message base
+ */
+ struct sadb_msg *msg;
+
+
+ /**
+ * PF_KEY message extensions
+ */
+ union {
+ struct sadb_ext *ext[SADB_EXT_MAX + 1];
+ struct {
+ struct sadb_ext *reserved; /* SADB_EXT_RESERVED */
+ struct sadb_sa *sa; /* SADB_EXT_SA */
+ struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */
+ struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */
+ struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */
+ struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */
+ struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */
+ struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */
+ struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */
+ struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */
+ struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */
+ struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */
+ struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */
+ struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */
+ struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */
+ struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */
+ struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */
+ struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */
+ struct sadb_ext *x_policy; /* SADB_X_EXT_SATYPE2 */
+ struct sadb_ext *x_sa2; /* SADB_X_EXT_SA2 */
+ struct sadb_address *x_dst2; /* SADB_X_EXT_ADDRESS_DST2 */
+ struct sadb_address *x_src_flow; /* SADB_X_EXT_ADDRESS_SRC_FLOW */
+ struct sadb_address *x_dst_flow; /* SADB_X_EXT_ADDRESS_DST_FLOW */
+ struct sadb_address *x_src_mask; /* SADB_X_EXT_ADDRESS_SRC_MASK */
+ struct sadb_address *x_dst_mask; /* SADB_X_EXT_ADDRESS_DST_MASK */
+ struct sadb_x_debug *x_debug; /* SADB_X_EXT_DEBUG */
+ struct sadb_protocol *x_protocol; /* SADB_X_EXT_PROTOCOL */
+ struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */
+ struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */
+ struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */
+ struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */
+ } __attribute__((__packed__));
+ };
+};
+
+/**
+ * convert a IKEv2 specific protocol identifier to the PF_KEY sa type
+ */
+static u_int8_t proto_ike2satype(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return SADB_SATYPE_ESP;
+ case PROTO_AH:
+ return SADB_SATYPE_AH;
+ case IPPROTO_COMP:
+ return SADB_X_SATYPE_COMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a PF_KEY sa type to a IKEv2 specific protocol identifier
+ */
+static protocol_id_t proto_satype2ike(u_int8_t proto)
+{
+ switch (proto)
+ {
+ case SADB_SATYPE_ESP:
+ return PROTO_ESP;
+ case SADB_SATYPE_AH:
+ return PROTO_AH;
+ case SADB_X_SATYPE_COMP:
+ return IPPROTO_COMP;
+ default:
+ return proto;
+ }
+}
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 algorithms to PF_KEY algorithms
+ */
+struct kernel_algorithm_t {
+ /**
+ * Identifier specified in IKEv2
+ */
+ int ikev2;
+
+ /**
+ * Identifier as defined in pfkeyv2.h
+ */
+ int kernel;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/* {ENCR_DES_IV64, 0 }, */
+ {ENCR_DES, SADB_EALG_DESCBC },
+ {ENCR_3DES, SADB_EALG_3DESCBC },
+/* {ENCR_RC5, 0 }, */
+/* {ENCR_IDEA, 0 }, */
+/* {ENCR_CAST, 0 }, */
+ {ENCR_BLOWFISH, SADB_EALG_BFCBC },
+/* {ENCR_3IDEA, 0 }, */
+/* {ENCR_DES_IV32, 0 }, */
+ {ENCR_NULL, SADB_EALG_NULL },
+ {ENCR_AES_CBC, SADB_EALG_AESCBC },
+/* {ENCR_AES_CTR, 0 }, */
+/* {ENCR_AES_CCM_ICV8, 0 }, */
+/* {ENCR_AES_CCM_ICV12, 0 }, */
+/* {ENCR_AES_CCM_ICV16, 0 }, */
+/* {ENCR_AES_GCM_ICV8, 0 }, */
+/* {ENCR_AES_GCM_ICV12, 0 }, */
+/* {ENCR_AES_GCM_ICV16, 0 }, */
+ {END_OF_LIST, 0 },
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+ {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC },
+ {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC },
+ {AUTH_HMAC_SHA2_256_128, SADB_AALG_SHA256_HMAC },
+ {AUTH_HMAC_SHA2_384_192, SADB_AALG_SHA384_HMAC },
+ {AUTH_HMAC_SHA2_512_256, SADB_AALG_SHA512_HMAC },
+/* {AUTH_DES_MAC, 0, }, */
+/* {AUTH_KPDK_MD5, 0, }, */
+/* {AUTH_AES_XCBC_96, 0, }, */
+ {END_OF_LIST, 0, },
+};
+
+#if 0
+/**
+ * Algorithms for IPComp, unused yet
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, 0 }, */
+ {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE },
+ {IPCOMP_LZS, SADB_X_CALG_LZS },
+/* {IPCOMP_LZJH, 0 }, */
+ {END_OF_LIST, 0 },
+};
+#endif
+
+/**
+ * Look up a kernel algorithm ID and its key size
+ */
+static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+{
+ while (list->ikev2 != END_OF_LIST)
+ {
+ if (ikev2 == list->ikev2)
+ {
+ return list->kernel;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * add a host behind a sadb_address extension
+ */
+static void host2ext(host_t *host, struct sadb_address *ext)
+{
+ sockaddr_t *host_addr = host->get_sockaddr(host);
+ socklen_t *len = host->get_sockaddr_len(host);
+ memcpy((char*)(ext + 1), host_addr, *len);
+ ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len);
+}
+
+/**
+ * add a host 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;
+ job_t *job;
+
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_UNSPEC:
+ case SADB_SATYPE_ESP:
+ case SADB_SATYPE_AH:
+ break;
+ default:
+ /* acquire for AH/ESP only */
+ return;
+ }
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed");
+ return;
+ }
+
+ /* KLIPS provides us only with the source and destination address,
+ * and the transport protocol of the packet that triggered the policy.
+ * we use this information to find a matching policy in our cache.
+ * because KLIPS installs a narrow %hold eroute covering only this information,
+ * we replace both the %trap and this %hold eroutes with a broader %hold
+ * eroute covering the whole policy */
+ src = host_create_from_sockaddr((sockaddr_t*)(response.src + 1));
+ dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1));
+ proto = response.src->sadb_address_proto;
+ if (!src || !dst || src->get_family(src) != dst->get_family(dst))
+ {
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE with invalid hosts");
+ return;
+ }
+
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE for %H == %H : %d", src, dst, proto);
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_match_byaddrs,
+ (void**)&policy, src, dst) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE, but found no matching policy");
+ return;
+ }
+ if ((reqid = policy->reqid) == 0)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE, but policy is not routed anymore");
+ return;
+ }
+
+ /* add a broad %hold eroute that replaces the %trap eroute */
+ add_eroute(this, SADB_X_SATYPE_INT, htonl(SPI_HOLD), NULL, NULL,
+ policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
+ policy->src.proto, TRUE);
+
+ /* remove the narrow %hold eroute installed by KLIPS */
+ del_eroute(this, SADB_X_SATYPE_INT, src, 32, dst, 32, proto);
+
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE");
+ DBG1(DBG_KNL, "creating acquire job for CHILD_SA with reqid {%d}", reqid);
+ job = (job_t*)acquire_job_create(reqid, NULL, NULL);
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
+ */
+static void process_mapping(private_kernel_klips_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t spi, reqid;
+ host_t *old_src, *new_src;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed");
+ return;
+ }
+
+ spi = response.sa->sadb_sa_spi;
+
+ if (proto_satype2ike(msg->sadb_msg_satype) == PROTO_ESP)
+ {
+ sa_entry_t *sa;
+ sockaddr_t *addr = (sockaddr_t*)(response.src + 1);
+ old_src = host_create_from_sockaddr(addr);
+
+ this->mutex->lock(this->mutex);
+ if (!old_src || this->installed_sas->find_first(this->installed_sas,
+ (linked_list_match_t)sa_entry_match_encapbysrc,
+ (void**)&sa, &spi, old_src) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING, but found no matching SA");
+ return;
+ }
+ reqid = sa->reqid;
+ this->mutex->unlock(this->mutex);
+
+ addr = (sockaddr_t*)(response.dst + 1);
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in*)addr;
+ sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
+ sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ default:
+ break;
+ }
+ new_src = host_create_from_sockaddr(addr);
+ if (new_src)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and"
+ " reqid {%d} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, new_src);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_klips_ipsec_t *this)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)buf;
+ int len;
+ 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 charon behave as with the other
+ * kernel plugins, we implement the expiration of SAs ourselves. */
+ break;
+ case SADB_X_NAT_T_NEW_MAPPING:
+ process_mapping(this, msg);
+ break;
+ default:
+ break;
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+typedef enum {
+ /** an SPI has expired */
+ EXPIRE_TYPE_SPI,
+ /** a CHILD_SA has to be rekeyed */
+ EXPIRE_TYPE_SOFT,
+ /** a CHILD_SA has to be deleted */
+ EXPIRE_TYPE_HARD
+} expire_type_t;
+
+typedef struct sa_expire_t sa_expire_t;
+
+struct sa_expire_t {
+ /** kernel interface */
+ private_kernel_klips_ipsec_t *this;
+ /** the SPI of the expiring SA */
+ u_int32_t spi;
+ /** the protocol of the expiring SA */
+ protocol_id_t protocol;
+ /** the reqid of the expiring SA*/
+ u_int32_t reqid;
+ /** what type of expire this is */
+ expire_type_t type;
+};
+
+/**
+ * Called when an SA expires
+ */
+static job_requeue_t sa_expires(sa_expire_t *expire)
+{
+ private_kernel_klips_ipsec_t *this = expire->this;
+ protocol_id_t protocol = expire->protocol;
+ u_int32_t spi = expire->spi, reqid = expire->reqid;
+ bool hard = expire->type != EXPIRE_TYPE_SOFT;
+ sa_entry_t *cached_sa;
+ linked_list_t *list;
+ job_t *job;
+
+ /* for an expired SPI we first check whether the CHILD_SA got installed
+ * in the meantime, for expired SAs we check whether they are still installed */
+ list = expire->type == EXPIRE_TYPE_SPI ? this->allocated_spis : this->installed_sas;
+
+ this->mutex->lock(this->mutex);
+ if (list->find_first(list, (linked_list_match_t)sa_entry_match_byid,
+ (void**)&cached_sa, &protocol, &spi, &reqid) != SUCCESS)
+ {
+ /* we found no entry:
+ * - for SPIs, a CHILD_SA has been installed
+ * - for SAs, the CHILD_SA has already been deleted */
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+ }
+ else
+ {
+ list->remove(list, cached_sa, NULL);
+ sa_entry_destroy(cached_sa);
+ }
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_KNL, "%N CHILD_SA with SPI %.8x and reqid {%d} expired",
+ protocol_id_names, protocol, ntohl(spi), reqid);
+
+ DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%d}",
+ hard ? "delete" : "rekey", protocol_id_names,
+ protocol, ntohl(spi), reqid);
+ if (hard)
+ {
+ job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
+ }
+ else
+ {
+ job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
+ }
+ charon->processor->queue_job(charon->processor, job);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedule an expire job for an SA. Time is in seconds.
+ */
+static void schedule_expire(private_kernel_klips_ipsec_t *this,
+ protocol_id_t protocol, u_int32_t spi,
+ u_int32_t reqid, expire_type_t type, u_int32_t time)
+{
+ callback_job_t *job;
+ sa_expire_t *expire = malloc_thing(sa_expire_t);
+ expire->this = this;
+ expire->protocol = protocol;
+ expire->spi = spi;
+ expire->reqid = reqid;
+ expire->type = type;
+ job = callback_job_create((callback_job_cb_t)sa_expires, expire, free, NULL);
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, time);
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+ private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi)
+{
+ /* we cannot use SADB_GETSPI because KLIPS does not allow us to set the
+ * NAT-T type in an SADB_UPDATE which we would have to use to update the
+ * implicitly created SA.
+ */
+ rng_t *rng;
+ u_int32_t spi_gen;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_KNL, "allocating SPI failed: no RNG");
+ return FAILED;
+ }
+ rng->get_bytes(rng, sizeof(spi_gen), (void*)&spi_gen);
+ rng->destroy(rng);
+
+ /* charon's SPIs lie within the range from 0xc0000000 to 0xcFFFFFFF */
+ spi_gen = 0xc0000000 | (spi_gen & 0x0FFFFFFF);
+
+ DBG2(DBG_KNL, "allocated SPI %.8x for %N SA between %#H..%#H",
+ spi_gen, protocol_id_names, protocol, src, dst);
+
+ *spi = htonl(spi_gen);
+
+ this->mutex->lock(this->mutex);
+ this->allocated_spis->insert_last(this->allocated_spis,
+ create_sa_entry(protocol, *spi, reqid, NULL, NULL, FALSE, TRUE));
+ this->mutex->unlock(this->mutex);
+ schedule_expire(this, protocol, *spi, reqid, EXPIRE_TYPE_SPI, SPI_TIMEOUT);
+
+ return SUCCESS;
+}
+
+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,
+ protocol_id_t protocol, u_int32_t reqid)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_x_satype *satype;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "grouping SAs with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_GRPSA;
+ msg->sadb_msg_satype = SADB_X_SATYPE_IPIP;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ satype = (struct sadb_x_satype*)PFKEY_EXT_ADD_NEXT(msg);
+ satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
+ satype->sadb_x_satype_len = PFKEY_LEN(sizeof(struct sadb_x_satype));
+ satype->sadb_x_satype_satype = proto_ike2satype(protocol);
+ PFKEY_EXT_ADD(msg, satype);
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_X_EXT_SA2;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, dst, SADB_X_EXT_ADDRESS_DST2);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to group SAs with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to group SAs with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+ private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid, 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 encap,
+ 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 = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
+ sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ if (enc_alg != ENCR_UNDEFINED)
+ {
+ if (!sa->sadb_sa_encrypt)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ encryption_algorithm_names, enc_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ key->sadb_key_bits = enc_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
+ memcpy(key + 1, enc_key.ptr, enc_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ if (!sa->sadb_sa_auth)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ integrity_algorithm_names, int_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
+ integrity_algorithm_names, int_alg, int_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ key->sadb_key_bits = int_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
+ memcpy(key + 1, int_key.ptr, int_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ /*TODO*/
+ }
+
+ if (encap)
+ {
+ add_encap_ext(msg, src, dst, FALSE);
+ }
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ /* for tunnel mode SAs we have to install an additional IPIP SA and
+ * group the two SAs together */
+ if (mode == MODE_TUNNEL)
+ {
+ if (add_ipip_sa(this, src, dst, spi, reqid) != SUCCESS ||
+ group_ipip_sa(this, src, dst, spi, protocol, reqid) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ }
+
+ this->mutex->lock(this->mutex);
+ /* we cache this SA for two reasons:
+ * - in case an SADB_X_NAT_T_MAPPING_NEW event occurs (we need to find the reqid then)
+ * - to decide if an expired SA is still installed */
+ this->installed_sas->insert_last(this->installed_sas,
+ create_sa_entry(protocol, spi, reqid, src, dst, encap, inbound));
+ this->mutex->unlock(this->mutex);
+
+ /* Although KLIPS supports SADB_EXT_LIFETIME_SOFT/HARD, we handle the lifetime
+ * of SAs manually in the plugin. Refer to the comments in receive_events()
+ * for details. */
+ if (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, protocol_id_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ size_t len;
+
+ /* we can't update the SA if any of the ip addresses have changed.
+ * that's because we can't use SADB_UPDATE and by deleting and readding the
+ * SA the sequence numbers would get lost */
+ if (!src->ip_equals(src, new_src) ||
+ !dst->ip_equals(dst, new_dst))
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes"
+ " are not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ /* because KLIPS does not allow us to change the NAT-T type in an SADB_UPDATE,
+ * we can't update the SA if the encap flag has changed since installing it */
+ if (encap != new_encap)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: change of UDP"
+ " encapsulation is not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_UPDATE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_encrypt = SADB_EALG_AESCBC; /* ignored */
+ sa->sadb_sa_auth = SADB_AALG_SHA1HMAC; /* ignored */
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ add_encap_ext(msg, new_src, new_dst, TRUE);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+ private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+{
+ 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, protocol_id_t protocol, u_int16_t cpi)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ sa_entry_t *cached_sa;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ /* all grouped SAs are automatically deleted by KLIPS as soon as
+ * one of them is deleted, therefore we delete only the main one */
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ this->mutex->lock(this->mutex);
+ /* this should not fail, but we don't care if it does, let the kernel decide
+ * whether this SA exists or not */
+ if (this->installed_sas->find_first(this->installed_sas,
+ (linked_list_match_t)sa_entry_match_bydst, (void**)&cached_sa,
+ &protocol, &spi, dst) == SUCCESS)
+ {
+ this->installed_sas->remove(this->installed_sas, cached_sa, NULL);
+ sa_entry_destroy(cached_sa);
+ }
+ this->mutex->unlock(this->mutex);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_DELETE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the kernel wants an SADB_EXT_ADDRESS_SRC to be present even though
+ * it is not used for anything. */
+ add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return SUCCESS;
+}
+
+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, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ policy_entry_t *policy, *found = NULL;
+ u_int8_t satype;
+ size_t len;
+
+ if (direction == POLICY_FWD)
+ {
+ /* no forward policies for KLIPS */
+ return SUCCESS;
+ }
+
+ /* tunnel mode policies direct the packets into the pseudo IPIP SA */
+ satype = (mode == MODE_TUNNEL) ? SADB_X_SATYPE_IPIP :
+ proto_ike2satype(protocol);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ /* use existing policy */
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing"
+ " refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ /* apply the new one, if we have no such policy */
+ this->policies->insert_last(this->policies, policy);
+ }
+
+ if (routed)
+ {
+ /* we install this as a %trap eroute in the kernel, later to be
+ * triggered by packets matching the policy (-> ACQUIRE). */
+ spi = htonl(SPI_TRAP);
+ satype = SADB_X_SATYPE_INT;
+
+ /* the reqid is always set to the latest child SA that trapped this
+ * policy. we will need this reqid upon receiving an acquire. */
+ policy->reqid = reqid;
+
+ /* increase the trap counter */
+ policy->trapcount++;
+
+ if (policy->activecount)
+ {
+ /* we do not replace the current policy in the kernel while a
+ * policy is actively used */
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ }
+ else
+ {
+ /* increase the reference counter */
+ policy->activecount++;
+ }
+
+ DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+
+ /* FIXME: SADB_X_SAFLAGS_INFLOW may be required, if we add an inbound policy for an IPIP SA */
+ build_addflow(msg, satype, spi, routed ? NULL : src, routed ? NULL : dst,
+ policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
+ policy->src.proto, found != NULL);
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts,
+ policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ this->mutex->lock(this->mutex);
+
+ /* we try to find the policy again and install the route if needed */
+ if (this->policies->find_last(this->policies, NULL, (void**)&policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG2(DBG_KNL, "the policy %R === %R %N is already gone, ignoring",
+ src_ts, dst_ts, policy_dir_names, direction);
+ return SUCCESS;
+ }
+
+ /* KLIPS requires a special route that directs traffic that matches this
+ * policy to one of the virtual ipsec interfaces. The virtual interface
+ * has to be attached to the physical one the traffic runs over.
+ * This is a special case of the source route we install in other kernel
+ * interfaces.
+ * In the following cases we do NOT install a source route (but just a
+ * regular route):
+ * - we are not in tunnel mode
+ * - we are using IPv6 (does not work correctly yet!)
+ * - routing is disabled via strongswan.conf
+ */
+ if (policy->route == NULL && direction == POLICY_OUT)
+ {
+ char *iface;
+ ipsec_dev_t *dev;
+ route_entry_t *route = malloc_thing(route_entry_t);
+ route->src_ip = NULL;
+
+ if (mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 &&
+ this->install_routes)
+ {
+ charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ src_ts, &route->src_ip);
+ }
+
+ if (!route->src_ip)
+ {
+ route->src_ip = host_create_any(src->get_family(src));
+ }
+
+ /* find the virtual interface */
+ iface = charon->kernel_interface->get_interface(charon->kernel_interface,
+ src);
+ if (find_ipsec_dev(this, iface, &dev) == SUCCESS)
+ {
+ /* above, we got either the name of a virtual or a physical
+ * interface. for both cases it means we already have the devices
+ * properly attached (assuming that we are exclusively attaching
+ * ipsec devices). */
+ dev->refcount++;
+ }
+ else
+ {
+ /* there is no record of a mapping with the returned interface.
+ * thus, we attach the first free virtual interface we find to
+ * it. As above we assume we are the only client fiddling with
+ * ipsec devices. */
+ if (this->ipsec_devices->find_first(this->ipsec_devices,
+ (linked_list_match_t)ipsec_dev_match_free,
+ (void**)&dev) == SUCCESS)
+ {
+ if (attach_ipsec_dev(dev->name, iface) == SUCCESS)
+ {
+ strncpy(dev->phys_name, iface, IFNAMSIZ);
+ dev->refcount = 1;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "failed to attach virtual interface %s"
+ " to %s", dev->name, iface);
+ this->mutex->unlock(this->mutex);
+ free(iface);
+ return FAILED;
+ }
+ }
+ else
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "failed to attach a virtual interface to %s: no"
+ " virtual interfaces left", iface);
+ free(iface);
+ return FAILED;
+ }
+ }
+ free(iface);
+ route->if_name = strdup(dev->name);
+
+ /* get the nexthop to dst */
+ route->gateway = charon->kernel_interface->get_nexthop(
+ charon->kernel_interface, dst);
+ route->dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net));
+ route->prefixlen = policy->dst.mask;
+
+ switch (charon->kernel_interface->add_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install route for policy %R === %R",
+ src_ts, dst_ts);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+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, u_int32_t *use_time)
+{
+ #define IDLE_PREFIX "idle="
+ static const char *path_eroute = "/proc/net/ipsec_eroute";
+ static const char *path_spi = "/proc/net/ipsec_spi";
+ FILE *file;
+ char line[1024], src[INET6_ADDRSTRLEN + 9], dst[INET6_ADDRSTRLEN + 9];
+ char *said = NULL, *pos;
+ policy_entry_t *policy, *found = NULL;
+ status_t status = FAILED;
+
+ if (direction == POLICY_FWD)
+ {
+ /* we do not install forward policies */
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+ policy = found;
+
+ /* src and dst selectors in KLIPS are of the form NET_ADDR/NETBITS:PROTO */
+ snprintf(src, sizeof(src), "%H/%d:%d", policy->src.net, policy->src.mask,
+ policy->src.proto);
+ src[sizeof(src) - 1] = '\0';
+ snprintf(dst, sizeof(dst), "%H/%d:%d", policy->dst.net, policy->dst.mask,
+ policy->dst.proto);
+ dst[sizeof(dst) - 1] = '\0';
+
+ this->mutex->unlock(this->mutex);
+
+ /* we try to find the matching eroute first */
+ file = fopen(path_eroute, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction, strerror(errno), errno);
+ return FAILED;
+ }
+
+ /* read line by line where each line looks like:
+ * packets src -> dst => said */
+ while (fgets(line, sizeof(line), file))
+ {
+ enumerator_t *enumerator;
+ char *token;
+ int i = 0;
+
+ enumerator = enumerator_create_token(line, " \t", " \t\n");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ switch (i++)
+ {
+ case 0: /* packets */
+ continue;
+ case 1: /* src */
+ if (streq(token, src))
+ {
+ continue;
+ }
+ break;
+ case 2: /* -> */
+ continue;
+ case 3: /* dst */
+ if (streq(token, dst))
+ {
+ continue;
+ }
+ break;
+ case 4: /* => */
+ continue;
+ case 5: /* said */
+ said = strdup(token);
+ break;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (i == 5)
+ {
+ /* eroute matched */
+ break;
+ }
+ }
+ fclose(file);
+
+ if (said == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: found no matching"
+ " eroute", src_ts, dst_ts, policy_dir_names, direction);
+ return FAILED;
+ }
+
+ /* compared with the one in the spi entry the SA ID from the eroute entry
+ * has an additional ":PROTO" appended, which we need to cut off */
+ pos = strrchr(said, ':');
+ *pos = '\0';
+
+ /* now we try to find the matching spi entry */
+ file = fopen(path_spi, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction, strerror(errno), errno);
+ return FAILED;
+ }
+
+ while (fgets(line, sizeof(line), file))
+ {
+ if (strneq(line, said, strlen(said)))
+ {
+ /* fine we found the correct line, now find the idle time */
+ u_int32_t idle_time;
+ pos = strstr(line, IDLE_PREFIX);
+ if (pos == NULL)
+ {
+ /* no idle time, i.e. this SA has not been used yet */
+ break;
+ }
+ if (sscanf(pos, IDLE_PREFIX"%u", &idle_time) <= 0)
+ {
+ /* idle time not valid */
+ break;
+ }
+
+ *use_time = time_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, bool unrouted)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)request, *out;
+ policy_entry_t *policy, *found = NULL;
+ route_entry_t *route;
+ size_t len;
+
+ if (direction == POLICY_FWD)
+ {
+ /* no forward policies for KLIPS */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+
+ /* decrease appropriate counter */
+ unrouted ? found->trapcount-- : found->activecount--;
+
+ if (found->trapcount == 0)
+ {
+ /* if this policy is finally unrouted, we reset the reqid because it
+ * may still be actively used and there might be a pending acquire for
+ * this policy. */
+ found->reqid = 0;
+ }
+
+ if (found->activecount > 0)
+ {
+ /* is still used by SAs, keep in kernel */
+ this->mutex->unlock(this->mutex);
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ return SUCCESS;
+ }
+ else if (found->activecount == 0 && found->trapcount > 0)
+ {
+ /* for a policy that is not used actively anymore, but is still trapped
+ * by another child SA we replace the current eroute with a %trap eroute */
+ DBG2(DBG_KNL, "policy still routed by another CHILD_SA, not removed");
+ memset(&request, 0, sizeof(request));
+ build_addflow(msg, SADB_X_SATYPE_INT, htonl(SPI_TRAP), NULL, NULL,
+ found->src.net, found->src.mask, found->dst.net,
+ found->dst.mask, found->src.proto, TRUE);
+ this->mutex->unlock(this->mutex);
+ return pfkey_send_ack(this, msg);
+ }
+
+ /* remove if last reference */
+ this->policies->remove(this->policies, found, NULL);
+ policy = found;
+
+ this->mutex->unlock(this->mutex);
+
+ memset(&request, 0, sizeof(request));
+
+ build_delflow(msg, 0, policy->src.net, policy->src.mask, policy->dst.net,
+ policy->dst.mask, policy->src.proto);
+
+ route = policy->route;
+ policy->route = NULL;
+ policy_entry_destroy(policy);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ if (route)
+ {
+ ipsec_dev_t *dev;
+
+ if (charon->kernel_interface->del_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "error uninstalling route installed with"
+ " policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
+
+ /* we have to detach the ipsec interface from the physical one over which
+ * this SA ran (if it is not used by any other) */
+ this->mutex->lock(this->mutex);
+
+ if (find_ipsec_dev(this, route->if_name, &dev) == SUCCESS)
+ {
+ /* fine, we found a matching device object, let's check if we have
+ * to detach it. */
+ if (--dev->refcount == 0)
+ {
+ if (detach_ipsec_dev(dev->name, dev->phys_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "failed to detach virtual interface %s"
+ " from %s", dev->name, dev->phys_name);
+ }
+ dev->phys_name[0] = '\0';
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ route_entry_destroy(route);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Initialize the list of ipsec devices
+ */
+static void init_ipsec_devices(private_kernel_klips_ipsec_t *this)
+{
+ int i, count = lib->settings->get_int(lib->settings,
+ "charon.plugins.kernel-klips.ipsec_dev_count",
+ DEFAULT_IPSEC_DEV_COUNT);
+
+ for (i = 0; i < count; ++i)
+ {
+ ipsec_dev_t *dev = malloc_thing(ipsec_dev_t);
+ snprintf(dev->name, IFNAMSIZ, IPSEC_DEV_PREFIX"%d", i);
+ dev->name[IFNAMSIZ - 1] = '\0';
+ dev->phys_name[0] = '\0';
+ dev->refcount = 0;
+ this->ipsec_devices->insert_last(this->ipsec_devices, dev);
+
+ /* detach any previously attached ipsec device */
+ detach_ipsec_dev(dev->name, dev->phys_name);
+ }
+}
+
+/**
+ * Register a socket for AQUIRE/EXPIRE messages
+ */
+static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8_t satype)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_REGISTER;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket");
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_klips_ipsec_t *this, int fd, int family)
+{
+ /* KLIPS does not need a bypass policy for IKE */
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_klips_ipsec_t *this)
+{
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ if (this->socket > 0)
+ {
+ close(this->socket);
+ }
+ if (this->socket_evnets > 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,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
+ .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,
+ "charon.install_routes", TRUE),
+ );
+
+ /* 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;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.h b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.h
new file mode 100644
index 000000000..306ec0ada
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.h
@@ -0,0 +1,46 @@
+/*
+ * 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/libcharon/plugins/kernel_klips/kernel_klips_plugin.c b/src/libcharon/plugins/kernel_klips/kernel_klips_plugin.c
new file mode 100644
index 000000000..fa5e9eb29
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_plugin.c
@@ -0,0 +1,56 @@
+/*
+ * 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 <daemon.h>
+
+typedef struct private_kernel_klips_plugin_t private_kernel_klips_plugin_t;
+
+/**
+ * private data of kernel PF_KEY plugin
+ */
+struct private_kernel_klips_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_klips_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_klips_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_klips_plugin_create()
+{
+ private_kernel_klips_plugin_t *this = malloc_thing(private_kernel_klips_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_plugin.h b/src/libcharon/plugins/kernel_klips/kernel_klips_plugin.h
new file mode 100644
index 000000000..6086217ad
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_klips kernel_klips
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_klips_plugin kernel_klips_plugin
+ * @{ @ingroup kernel_klips
+ */
+
+#ifndef KERNEL_KLIPS_PLUGIN_H_
+#define KERNEL_KLIPS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_klips_plugin_t kernel_klips_plugin_t;
+
+/**
+ * PF_KEY kernel interface plugin
+ */
+struct kernel_klips_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_KLIPS_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_klips/pfkeyv2.h b/src/libcharon/plugins/kernel_klips/pfkeyv2.h
new file mode 100644
index 000000000..20d1c298d
--- /dev/null
+++ b/src/libcharon/plugins/kernel_klips/pfkeyv2.h
@@ -0,0 +1,322 @@
+/*
+RFC 2367 PF_KEY Key Management API July 1998
+
+
+Appendix D: Sample Header File
+
+This file defines structures and symbols for the PF_KEY Version 2
+key management interface. It was written at the U.S. Naval Research
+Laboratory. This file is in the public domain. The authors ask that
+you leave this credit intact on any copies of this file.
+*/
+#ifndef __PFKEY_V2_H
+#define __PFKEY_V2_H 1
+
+#define PF_KEY_V2 2
+#define PFKEYV2_REVISION 199806L
+
+#define SADB_RESERVED 0
+#define SADB_GETSPI 1
+#define SADB_UPDATE 2
+#define SADB_ADD 3
+#define SADB_DELETE 4
+#define SADB_GET 5
+#define SADB_ACQUIRE 6
+#define SADB_REGISTER 7
+#define SADB_EXPIRE 8
+#define SADB_FLUSH 9
+#define SADB_DUMP 10
+#define SADB_X_PROMISC 11
+#define SADB_X_PCHANGE 12
+#define SADB_X_GRPSA 13
+#define SADB_X_ADDFLOW 14
+#define SADB_X_DELFLOW 15
+#define SADB_X_DEBUG 16
+#define SADB_X_NAT_T_NEW_MAPPING 17
+#define SADB_MAX 17
+
+struct sadb_msg {
+ uint8_t sadb_msg_version;
+ uint8_t sadb_msg_type;
+ uint8_t sadb_msg_errno;
+ uint8_t sadb_msg_satype;
+ uint16_t sadb_msg_len;
+ uint16_t sadb_msg_reserved;
+ uint32_t sadb_msg_seq;
+ uint32_t sadb_msg_pid;
+};
+
+struct sadb_ext {
+ uint16_t sadb_ext_len;
+ uint16_t sadb_ext_type;
+};
+
+struct sadb_sa {
+ uint16_t sadb_sa_len;
+ uint16_t sadb_sa_exttype;
+ uint32_t sadb_sa_spi;
+ uint8_t sadb_sa_replay;
+ uint8_t sadb_sa_state;
+ uint8_t sadb_sa_auth;
+ uint8_t sadb_sa_encrypt;
+ uint32_t sadb_sa_flags;
+};
+
+struct sadb_lifetime {
+ uint16_t sadb_lifetime_len;
+ uint16_t sadb_lifetime_exttype;
+ uint32_t sadb_lifetime_allocations;
+ uint64_t sadb_lifetime_bytes;
+ uint64_t sadb_lifetime_addtime;
+ uint64_t sadb_lifetime_usetime;
+ uint32_t sadb_x_lifetime_packets;
+ uint32_t sadb_x_lifetime_reserved;
+};
+
+struct sadb_address {
+ uint16_t sadb_address_len;
+ uint16_t sadb_address_exttype;
+ uint8_t sadb_address_proto;
+ uint8_t sadb_address_prefixlen;
+ uint16_t sadb_address_reserved;
+};
+
+struct sadb_key {
+ uint16_t sadb_key_len;
+ uint16_t sadb_key_exttype;
+ uint16_t sadb_key_bits;
+ uint16_t sadb_key_reserved;
+};
+
+struct sadb_ident {
+ uint16_t sadb_ident_len;
+ uint16_t sadb_ident_exttype;
+ uint16_t sadb_ident_type;
+ uint16_t sadb_ident_reserved;
+ uint64_t sadb_ident_id;
+};
+
+struct sadb_sens {
+ uint16_t sadb_sens_len;
+ uint16_t sadb_sens_exttype;
+ uint32_t sadb_sens_dpd;
+ uint8_t sadb_sens_sens_level;
+ uint8_t sadb_sens_sens_len;
+ uint8_t sadb_sens_integ_level;
+ uint8_t sadb_sens_integ_len;
+ uint32_t sadb_sens_reserved;
+};
+
+struct sadb_prop {
+ uint16_t sadb_prop_len;
+ uint16_t sadb_prop_exttype;
+ uint8_t sadb_prop_replay;
+ uint8_t sadb_prop_reserved[3];
+};
+
+struct sadb_comb {
+ uint8_t sadb_comb_auth;
+ uint8_t sadb_comb_encrypt;
+ uint16_t sadb_comb_flags;
+ uint16_t sadb_comb_auth_minbits;
+ uint16_t sadb_comb_auth_maxbits;
+ uint16_t sadb_comb_encrypt_minbits;
+ uint16_t sadb_comb_encrypt_maxbits;
+ uint32_t sadb_comb_reserved;
+ uint32_t sadb_comb_soft_allocations;
+ uint32_t sadb_comb_hard_allocations;
+ uint64_t sadb_comb_soft_bytes;
+ uint64_t sadb_comb_hard_bytes;
+ uint64_t sadb_comb_soft_addtime;
+ uint64_t sadb_comb_hard_addtime;
+ uint64_t sadb_comb_soft_usetime;
+ uint64_t sadb_comb_hard_usetime;
+ uint32_t sadb_x_comb_soft_packets;
+ uint32_t sadb_x_comb_hard_packets;
+};
+
+struct sadb_supported {
+ uint16_t sadb_supported_len;
+ uint16_t sadb_supported_exttype;
+ uint32_t sadb_supported_reserved;
+};
+
+struct sadb_alg {
+ uint8_t sadb_alg_id;
+ uint8_t sadb_alg_ivlen;
+ uint16_t sadb_alg_minbits;
+ uint16_t sadb_alg_maxbits;
+ uint16_t sadb_alg_reserved;
+};
+
+struct sadb_spirange {
+ uint16_t sadb_spirange_len;
+ uint16_t sadb_spirange_exttype;
+ uint32_t sadb_spirange_min;
+ uint32_t sadb_spirange_max;
+ uint32_t sadb_spirange_reserved;
+};
+
+struct sadb_x_kmprivate {
+ uint16_t sadb_x_kmprivate_len;
+ uint16_t sadb_x_kmprivate_exttype;
+ uint32_t sadb_x_kmprivate_reserved;
+};
+
+struct sadb_x_satype {
+ uint16_t sadb_x_satype_len;
+ uint16_t sadb_x_satype_exttype;
+ uint8_t sadb_x_satype_satype;
+ uint8_t sadb_x_satype_reserved[3];
+};
+
+struct sadb_x_debug {
+ uint16_t sadb_x_debug_len;
+ uint16_t sadb_x_debug_exttype;
+ uint32_t sadb_x_debug_tunnel;
+ uint32_t sadb_x_debug_netlink;
+ uint32_t sadb_x_debug_xform;
+ uint32_t sadb_x_debug_eroute;
+ uint32_t sadb_x_debug_spi;
+ uint32_t sadb_x_debug_radij;
+ uint32_t sadb_x_debug_esp;
+ uint32_t sadb_x_debug_ah;
+ uint32_t sadb_x_debug_rcv;
+ uint32_t sadb_x_debug_pfkey;
+ uint32_t sadb_x_debug_ipcomp;
+ uint32_t sadb_x_debug_verbose;
+ uint8_t sadb_x_debug_reserved[4];
+};
+
+struct sadb_x_nat_t_type {
+ uint16_t sadb_x_nat_t_type_len;
+ uint16_t sadb_x_nat_t_type_exttype;
+ uint8_t sadb_x_nat_t_type_type;
+ uint8_t sadb_x_nat_t_type_reserved[3];
+};
+struct sadb_x_nat_t_port {
+ uint16_t sadb_x_nat_t_port_len;
+ uint16_t sadb_x_nat_t_port_exttype;
+ uint16_t sadb_x_nat_t_port_port;
+ uint16_t sadb_x_nat_t_port_reserved;
+};
+
+/*
+ * A protocol structure for passing through the transport level
+ * protocol. It contains more fields than are actually used/needed
+ * but it is this way to be compatible with the structure used in
+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
+ */
+struct sadb_protocol {
+ uint16_t sadb_protocol_len;
+ uint16_t sadb_protocol_exttype;
+ uint8_t sadb_protocol_proto;
+ uint8_t sadb_protocol_direction;
+ uint8_t sadb_protocol_flags;
+ uint8_t sadb_protocol_reserved2;
+};
+
+#define SADB_EXT_RESERVED 0
+#define SADB_EXT_SA 1
+#define SADB_EXT_LIFETIME_CURRENT 2
+#define SADB_EXT_LIFETIME_HARD 3
+#define SADB_EXT_LIFETIME_SOFT 4
+#define SADB_EXT_ADDRESS_SRC 5
+#define SADB_EXT_ADDRESS_DST 6
+#define SADB_EXT_ADDRESS_PROXY 7
+#define SADB_EXT_KEY_AUTH 8
+#define SADB_EXT_KEY_ENCRYPT 9
+#define SADB_EXT_IDENTITY_SRC 10
+#define SADB_EXT_IDENTITY_DST 11
+#define SADB_EXT_SENSITIVITY 12
+#define SADB_EXT_PROPOSAL 13
+#define SADB_EXT_SUPPORTED_AUTH 14
+#define SADB_EXT_SUPPORTED_ENCRYPT 15
+#define SADB_EXT_SPIRANGE 16
+#define SADB_X_EXT_KMPRIVATE 17
+#define SADB_X_EXT_SATYPE2 18
+#define SADB_X_EXT_SA2 19
+#define SADB_X_EXT_ADDRESS_DST2 20
+#define SADB_X_EXT_ADDRESS_SRC_FLOW 21
+#define SADB_X_EXT_ADDRESS_DST_FLOW 22
+#define SADB_X_EXT_ADDRESS_SRC_MASK 23
+#define SADB_X_EXT_ADDRESS_DST_MASK 24
+#define SADB_X_EXT_DEBUG 25
+#define SADB_X_EXT_PROTOCOL 26
+#define SADB_X_EXT_NAT_T_TYPE 27
+#define SADB_X_EXT_NAT_T_SPORT 28
+#define SADB_X_EXT_NAT_T_DPORT 29
+#define SADB_X_EXT_NAT_T_OA 30
+#define SADB_EXT_MAX 30
+
+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
+#define SADB_X_EXT_ADDRESS_DELFLOW \
+ ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_MASK))
+
+#define SADB_SATYPE_UNSPEC 0
+#define SADB_SATYPE_AH 2
+#define SADB_SATYPE_ESP 3
+#define SADB_SATYPE_RSVP 5
+#define SADB_SATYPE_OSPFV2 6
+#define SADB_SATYPE_RIPV2 7
+#define SADB_SATYPE_MIP 8
+#define SADB_X_SATYPE_IPIP 9
+#define SADB_X_SATYPE_COMP 10
+#define SADB_X_SATYPE_INT 11
+#define SADB_SATYPE_MAX 11
+
+#define SADB_SASTATE_LARVAL 0
+#define SADB_SASTATE_MATURE 1
+#define SADB_SASTATE_DYING 2
+#define SADB_SASTATE_DEAD 3
+#define SADB_SASTATE_MAX 3
+
+#define SADB_SAFLAGS_PFS 1
+#define SADB_X_SAFLAGS_REPLACEFLOW 2
+#define SADB_X_SAFLAGS_CLEARFLOW 4
+#define SADB_X_SAFLAGS_INFLOW 8
+
+#define SADB_AALG_NONE 0
+#define SADB_AALG_MD5HMAC 2
+#define SADB_AALG_SHA1HMAC 3
+#define SADB_AALG_SHA256_HMAC 5
+#define SADB_AALG_SHA384_HMAC 6
+#define SADB_AALG_SHA512_HMAC 7
+#define SADB_AALG_RIPEMD160HMAC 8
+#define SADB_AALG_MAX 15
+
+#define SADB_EALG_NONE 0
+#define SADB_EALG_DESCBC 2
+#define SADB_EALG_3DESCBC 3
+#define SADB_EALG_BFCBC 7
+#define SADB_EALG_NULL 11
+#define SADB_EALG_AESCBC 12
+#define SADB_EALG_MAX 255
+
+#define SADB_X_CALG_NONE 0
+#define SADB_X_CALG_OUI 1
+#define SADB_X_CALG_DEFLATE 2
+#define SADB_X_CALG_LZS 3
+#define SADB_X_CALG_V42BIS 4
+#define SADB_X_CALG_MAX 4
+
+#define SADB_X_TALG_NONE 0
+#define SADB_X_TALG_IPv4_in_IPv4 1
+#define SADB_X_TALG_IPv6_in_IPv4 2
+#define SADB_X_TALG_IPv4_in_IPv6 3
+#define SADB_X_TALG_IPv6_in_IPv6 4
+#define SADB_X_TALG_MAX 4
+
+
+#define SADB_IDENTTYPE_RESERVED 0
+#define SADB_IDENTTYPE_PREFIX 1
+#define SADB_IDENTTYPE_FQDN 2
+#define SADB_IDENTTYPE_USERFQDN 3
+#define SADB_X_IDENTTYPE_CONNECTION 4
+#define SADB_IDENTTYPE_MAX 4
+
+#define SADB_KEY_FLAGS_MAX 0
+#endif /* __PFKEY_V2_H */
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.am b/src/libcharon/plugins/kernel_netlink/Makefile.am
new file mode 100644
index 000000000..2bb00ec0d
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.am
@@ -0,0 +1,20 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+-DROUTING_TABLE=${routing_table} \
+-DROUTING_TABLE_PRIO=${routing_table_prio}
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
+endif
+
+libstrongswan_kernel_netlink_la_SOURCES = \
+ kernel_netlink_plugin.h kernel_netlink_plugin.c \
+ kernel_netlink_ipsec.h kernel_netlink_ipsec.c kernel_netlink_net.h kernel_netlink_net.c \
+ kernel_netlink_shared.h kernel_netlink_shared.c
+
+libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in
new file mode 100644
index 000000000..8c9965467
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.in
@@ -0,0 +1,597 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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_netlink
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_netlink_la_LIBADD =
+am_libstrongswan_kernel_netlink_la_OBJECTS = kernel_netlink_plugin.lo \
+ kernel_netlink_ipsec.lo kernel_netlink_net.lo \
+ kernel_netlink_shared.lo
+libstrongswan_kernel_netlink_la_OBJECTS = \
+ $(am_libstrongswan_kernel_netlink_la_OBJECTS)
+libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_netlink_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_netlink_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_netlink_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+-DROUTING_TABLE=${routing_table} \
+-DROUTING_TABLE_PRIO=${routing_table_prio}
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
+libstrongswan_kernel_netlink_la_SOURCES = \
+ kernel_netlink_plugin.h kernel_netlink_plugin.c \
+ kernel_netlink_ipsec.h kernel_netlink_ipsec.c kernel_netlink_net.h kernel_netlink_net.c \
+ kernel_netlink_shared.h kernel_netlink_shared.c
+
+libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-netlink.la: $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_DEPENDENCIES)
+ $(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_netlink_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_netlink_net.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_netlink_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_netlink_shared.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
new file mode 100644
index 000000000..1b8c1b879
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -0,0 +1,2032 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2008 Andreas Steffen
+ * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdint.h>
+#include <linux/ipsec.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/xfrm.h>
+#include <linux/udp.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "kernel_netlink_ipsec.h"
+#include "kernel_netlink_shared.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <utils/hashtable.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/migrate_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
+
+/** required for Linux 2.6.26 kernel and later */
+#ifndef XFRM_STATE_AF_UNSPEC
+#define XFRM_STATE_AF_UNSPEC 32
+#endif
+
+/** from linux/in.h */
+#ifndef IP_XFRM_POLICY
+#define IP_XFRM_POLICY 17
+#endif
+
+/* missing on uclibc */
+#ifndef IPV6_XFRM_POLICY
+#define IPV6_XFRM_POLICY 34
+#endif /*IPV6_XFRM_POLICY*/
+
+/** default priority of installed policies */
+#define PRIO_LOW 3000
+#define PRIO_HIGH 2000
+
+/**
+ * map the limit for bytes and packets to XFRM_INF per default
+ */
+#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x))
+
+/**
+ * Create ORable bitfield of XFRM NL groups
+ */
+#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1))
+
+/**
+ * returns a pointer to the first rtattr following the nlmsghdr *nlh and the
+ * 'usual' netlink data x like 'struct xfrm_usersa_info'
+ */
+#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(x))))
+/**
+ * returns a pointer to the next rtattr following rta.
+ * !!! do not use this to parse messages. use RTA_NEXT and RTA_OK instead !!!
+ */
+#define XFRM_RTA_NEXT(rta) ((struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
+/**
+ * returns the total size of attached rta data
+ * (after 'usual' netlink data x like 'struct xfrm_usersa_info')
+ */
+#define XFRM_PAYLOAD(nlh, x) NLMSG_PAYLOAD(nlh, sizeof(x))
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 kernel identifier to linux crypto API names
+ */
+struct kernel_algorithm_t {
+ /**
+ * Identifier specified in IKEv2
+ */
+ int ikev2;
+
+ /**
+ * Name of the algorithm in linux crypto API
+ */
+ char *name;
+};
+
+ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
+ "XFRM_MSG_NEWSA",
+ "XFRM_MSG_DELSA",
+ "XFRM_MSG_GETSA",
+ "XFRM_MSG_NEWPOLICY",
+ "XFRM_MSG_DELPOLICY",
+ "XFRM_MSG_GETPOLICY",
+ "XFRM_MSG_ALLOCSPI",
+ "XFRM_MSG_ACQUIRE",
+ "XFRM_MSG_EXPIRE",
+ "XFRM_MSG_UPDPOLICY",
+ "XFRM_MSG_UPDSA",
+ "XFRM_MSG_POLEXPIRE",
+ "XFRM_MSG_FLUSHSA",
+ "XFRM_MSG_FLUSHPOLICY",
+ "XFRM_MSG_NEWAE",
+ "XFRM_MSG_GETAE",
+ "XFRM_MSG_REPORT",
+ "XFRM_MSG_MIGRATE",
+ "XFRM_MSG_NEWSADINFO",
+ "XFRM_MSG_GETSADINFO",
+ "XFRM_MSG_NEWSPDINFO",
+ "XFRM_MSG_GETSPDINFO",
+ "XFRM_MSG_MAPPING"
+);
+
+ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_KMADDRESS,
+ "XFRMA_UNSPEC",
+ "XFRMA_ALG_AUTH",
+ "XFRMA_ALG_CRYPT",
+ "XFRMA_ALG_COMP",
+ "XFRMA_ENCAP",
+ "XFRMA_TMPL",
+ "XFRMA_SA",
+ "XFRMA_POLICY",
+ "XFRMA_SEC_CTX",
+ "XFRMA_LTIME_VAL",
+ "XFRMA_REPLAY_VAL",
+ "XFRMA_REPLAY_THRESH",
+ "XFRMA_ETIMER_THRESH",
+ "XFRMA_SRCADDR",
+ "XFRMA_COADDR",
+ "XFRMA_LASTUSED",
+ "XFRMA_POLICY_TYPE",
+ "XFRMA_MIGRATE",
+ "XFRMA_ALG_AEAD",
+ "XFRMA_KMADDRESS"
+);
+
+#define END_OF_LIST -1
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/* {ENCR_DES_IV64, "***" }, */
+ {ENCR_DES, "des" },
+ {ENCR_3DES, "des3_ede" },
+/* {ENCR_RC5, "***" }, */
+/* {ENCR_IDEA, "***" }, */
+ {ENCR_CAST, "cast128" },
+ {ENCR_BLOWFISH, "blowfish" },
+/* {ENCR_3IDEA, "***" }, */
+/* {ENCR_DES_IV32, "***" }, */
+ {ENCR_NULL, "cipher_null" },
+ {ENCR_AES_CBC, "aes" },
+ {ENCR_AES_CTR, "rfc3686(ctr(aes))" },
+ {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))" },
+ {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))" },
+ {ENCR_NULL_AUTH_AES_GMAC, "rfc4543(gcm(aes))" },
+ {ENCR_CAMELLIA_CBC, "cbc(camellia)" },
+/* {ENCR_CAMELLIA_CTR, "***" }, */
+/* {ENCR_CAMELLIA_CCM_ICV8, "***" }, */
+/* {ENCR_CAMELLIA_CCM_ICV12, "***" }, */
+/* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */
+ {END_OF_LIST, NULL }
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+ {AUTH_HMAC_MD5_96, "md5" },
+ {AUTH_HMAC_SHA1_96, "sha1" },
+ {AUTH_HMAC_SHA2_256_96, "sha256" },
+ {AUTH_HMAC_SHA2_256_128, "hmac(sha256)" },
+ {AUTH_HMAC_SHA2_384_192, "hmac(sha384)" },
+ {AUTH_HMAC_SHA2_512_256, "hmac(sha512)" },
+/* {AUTH_DES_MAC, "***" }, */
+/* {AUTH_KPDK_MD5, "***" }, */
+ {AUTH_AES_XCBC_96, "xcbc(aes)" },
+ {END_OF_LIST, NULL }
+};
+
+/**
+ * Algorithms for IPComp
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, "***" }, */
+ {IPCOMP_DEFLATE, "deflate" },
+ {IPCOMP_LZS, "lzs" },
+ {IPCOMP_LZJH, "lzjh" },
+ {END_OF_LIST, NULL }
+};
+
+/**
+ * Look up a kernel algorithm name and its key size
+ */
+static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+{
+ while (list->ikev2 != END_OF_LIST)
+ {
+ if (list->ikev2 == ikev2)
+ {
+ return list->name;
+ }
+ list++;
+ }
+ return NULL;
+}
+
+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);
+ DESTROY_IF(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+
+ /** direction of this policy: in, out, forward */
+ u_int8_t direction;
+
+ /** parameters of installed policy */
+ struct xfrm_selector sel;
+
+ /** associated route installed for this policy */
+ route_entry_t *route;
+
+ /** by how many CHILD_SA's this policy is used */
+ u_int refcount;
+};
+
+/**
+ * Hash function for policy_entry_t objects
+ */
+static u_int policy_hash(policy_entry_t *key)
+{
+ chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+ return chunk_hash(chunk);
+}
+
+/**
+ * Equality function for policy_entry_t objects
+ */
+static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
+{
+ return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ key->direction == other_key->direction;
+}
+
+typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_netlink class.
+ */
+struct private_kernel_netlink_ipsec_t {
+ /**
+ * Public part of the kernel_netlink_t object.
+ */
+ kernel_netlink_ipsec_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * Hash table of installed policies (policy_entry_t)
+ */
+ hashtable_t *policies;
+
+ /**
+ * job receiving netlink events
+ */
+ callback_job_t *job;
+
+ /**
+ * Netlink xfrm socket (IPsec)
+ */
+ netlink_socket_t *socket_xfrm;
+
+ /**
+ * netlink xfrm socket to receive acquire and expire events
+ */
+ int socket_xfrm_events;
+
+ /**
+ * whether to install routes along policies
+ */
+ bool install_routes;
+};
+
+/**
+ * convert a IKEv2 specific protocol identifier to the kernel one
+ */
+static u_int8_t proto_ike2kernel(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return IPPROTO_ESP;
+ case PROTO_AH:
+ return IPPROTO_AH;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * reverse of ike2kernel
+ */
+static protocol_id_t proto_kernel2ike(u_int8_t proto)
+{
+ switch (proto)
+ {
+ case IPPROTO_ESP:
+ return PROTO_ESP;
+ case IPPROTO_AH:
+ return PROTO_AH;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert the general ipsec mode to the one defined in xfrm.h
+ */
+static u_int8_t mode2kernel(ipsec_mode_t mode)
+{
+ switch (mode)
+ {
+ case MODE_TRANSPORT:
+ return XFRM_MODE_TRANSPORT;
+ case MODE_TUNNEL:
+ return XFRM_MODE_TUNNEL;
+ case MODE_BEET:
+ return XFRM_MODE_BEET;
+ default:
+ return mode;
+ }
+}
+
+/**
+ * convert a host_t to a struct xfrm_address
+ */
+static void host2xfrm(host_t *host, xfrm_address_t *xfrm)
+{
+ chunk_t chunk = host->get_address(host);
+ memcpy(xfrm, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t)));
+}
+
+/**
+ * convert a struct xfrm_address to a host_t
+ */
+static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port)
+{
+ chunk_t chunk;
+
+ switch (family)
+ {
+ case AF_INET:
+ chunk = chunk_create((u_char*)&xfrm->a4, sizeof(xfrm->a4));
+ break;
+ case AF_INET6:
+ chunk = chunk_create((u_char*)&xfrm->a6, sizeof(xfrm->a6));
+ break;
+ default:
+ return NULL;
+ }
+ return host_create_from_chunk(family, chunk, ntohs(port));
+}
+
+/**
+ * convert a traffic selector address range to subnet and its mask.
+ */
+static void ts2subnet(traffic_selector_t* ts,
+ xfrm_address_t *net, u_int8_t *mask)
+{
+ host_t *net_host;
+ chunk_t net_chunk;
+
+ ts->to_subnet(ts, &net_host, mask);
+ net_chunk = net_host->get_address(net_host);
+ memcpy(net, net_chunk.ptr, net_chunk.len);
+ net_host->destroy(net_host);
+}
+
+/**
+ * convert a traffic selector port range to port/portmask
+ */
+static void ts2ports(traffic_selector_t* ts,
+ u_int16_t *port, u_int16_t *mask)
+{
+ /* linux does not seem to accept complex portmasks. Only
+ * any or a specific port is allowed. We set to any, if we have
+ * a port range, or to a specific, if we have one port only.
+ */
+ u_int16_t from, to;
+
+ from = ts->get_from_port(ts);
+ to = ts->get_to_port(ts);
+
+ if (from == to)
+ {
+ *port = htons(from);
+ *mask = ~0;
+ }
+ else
+ {
+ *port = 0;
+ *mask = 0;
+ }
+}
+
+/**
+ * convert a pair of traffic_selectors to a xfrm_selector
+ */
+static struct xfrm_selector ts2selector(traffic_selector_t *src,
+ traffic_selector_t *dst)
+{
+ struct xfrm_selector sel;
+
+ memset(&sel, 0, sizeof(sel));
+ sel.family = (src->get_type(src) == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ /* src or dest proto may be "any" (0), use more restrictive one */
+ sel.proto = max(src->get_protocol(src), dst->get_protocol(dst));
+ ts2subnet(dst, &sel.daddr, &sel.prefixlen_d);
+ ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
+ ts2ports(dst, &sel.dport, &sel.dport_mask);
+ ts2ports(src, &sel.sport, &sel.sport_mask);
+ sel.ifindex = 0;
+ sel.user = 0;
+
+ return sel;
+}
+
+/**
+ * convert a xfrm_selector to a src|dst traffic_selector
+ */
+static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
+{
+ u_char *addr;
+ u_int8_t prefixlen;
+ u_int16_t port = 0;
+ host_t *host = NULL;
+
+ if (src)
+ {
+ addr = (u_char*)&sel->saddr;
+ prefixlen = sel->prefixlen_s;
+ if (sel->sport_mask)
+ {
+ port = htons(sel->sport);
+ }
+ }
+ else
+ {
+ addr = (u_char*)&sel->daddr;
+ prefixlen = sel->prefixlen_d;
+ if (sel->dport_mask)
+ {
+ port = htons(sel->dport);
+ }
+ }
+
+ /* The Linux 2.6 kernel does not set the selector's family field,
+ * so as a kludge we additionally test the prefix length.
+ */
+ if (sel->family == AF_INET || sel->prefixlen_s == 32)
+ {
+ host = host_create_from_chunk(AF_INET, chunk_create(addr, 4), 0);
+ }
+ else if (sel->family == AF_INET6 || sel->prefixlen_s == 128)
+ {
+ host = host_create_from_chunk(AF_INET6, chunk_create(addr, 16), 0);
+ }
+
+ if (host)
+ {
+ return traffic_selector_create_from_subnet(host, prefixlen,
+ sel->proto, port);
+ }
+ return NULL;
+}
+
+/**
+ * process a XFRM_MSG_ACQUIRE from kernel
+ */
+static void process_acquire(private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ u_int32_t reqid = 0;
+ int proto = 0;
+ traffic_selector_t *src_ts, *dst_ts;
+ struct xfrm_user_acquire *acquire;
+ struct rtattr *rta;
+ size_t rtasize;
+ job_t *job;
+
+ acquire = (struct xfrm_user_acquire*)NLMSG_DATA(hdr);
+ rta = XFRM_RTA(hdr, struct xfrm_user_acquire);
+ rtasize = XFRM_PAYLOAD(hdr, struct xfrm_user_acquire);
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_ACQUIRE");
+
+ while (RTA_OK(rta, rtasize))
+ {
+ DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type);
+
+ if (rta->rta_type == XFRMA_TMPL)
+ {
+ struct xfrm_user_tmpl* tmpl;
+
+ tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rta);
+ reqid = tmpl->reqid;
+ proto = tmpl->id.proto;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ switch (proto)
+ {
+ case 0:
+ case IPPROTO_ESP:
+ case IPPROTO_AH:
+ break;
+ default:
+ /* acquire for AH/ESP only, not for IPCOMP */
+ return;
+ }
+ src_ts = selector2ts(&acquire->sel, TRUE);
+ dst_ts = selector2ts(&acquire->sel, FALSE);
+ DBG1(DBG_KNL, "creating acquire job for policy %R === %R with reqid {%u}",
+ src_ts, dst_ts, reqid);
+ job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts);
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * process a XFRM_MSG_EXPIRE from kernel
+ */
+static void process_expire(private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ job_t *job;
+ protocol_id_t protocol;
+ u_int32_t spi, reqid;
+ struct xfrm_user_expire *expire;
+
+ expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr);
+ protocol = proto_kernel2ike(expire->state.id.proto);
+ spi = expire->state.id.spi;
+ reqid = expire->state.reqid;
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE");
+
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ DBG2(DBG_KNL, "ignoring XFRM_MSG_EXPIRE for SA with SPI %.8x and reqid {%u} "
+ "which is not a CHILD_SA", ntohl(spi), reqid);
+ return;
+ }
+
+ DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%d}",
+ expire->hard ? "delete" : "rekey", protocol_id_names,
+ protocol, ntohl(spi), reqid);
+ if (expire->hard)
+ {
+ job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
+ }
+ else
+ {
+ job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
+ }
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * process a XFRM_MSG_MIGRATE from kernel
+ */
+static void process_migrate(private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ traffic_selector_t *src_ts, *dst_ts;
+ host_t *local = NULL, *remote = NULL;
+ host_t *old_src = NULL, *old_dst = NULL;
+ host_t *new_src = NULL, *new_dst = NULL;
+ struct xfrm_userpolicy_id *policy_id;
+ struct rtattr *rta;
+ size_t rtasize;
+ u_int32_t reqid = 0;
+ policy_dir_t dir;
+ job_t *job;
+
+ policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ rta = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+ rtasize = XFRM_PAYLOAD(hdr, struct xfrm_userpolicy_id);
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_MIGRATE");
+
+ src_ts = selector2ts(&policy_id->sel, TRUE);
+ dst_ts = selector2ts(&policy_id->sel, FALSE);
+ dir = (policy_dir_t)policy_id->dir;
+
+ DBG2(DBG_KNL, " policy: %R === %R %N", src_ts, dst_ts, policy_dir_names);
+
+ while (RTA_OK(rta, rtasize))
+ {
+ DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type);
+ if (rta->rta_type == XFRMA_KMADDRESS)
+ {
+ struct xfrm_user_kmaddress *kmaddress;
+
+ kmaddress = (struct xfrm_user_kmaddress*)RTA_DATA(rta);
+ local = xfrm2host(kmaddress->family, &kmaddress->local, 0);
+ remote = xfrm2host(kmaddress->family, &kmaddress->remote, 0);
+ DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote);
+ }
+ else if (rta->rta_type == XFRMA_MIGRATE)
+ {
+ struct xfrm_user_migrate *migrate;
+ protocol_id_t proto;
+
+ migrate = (struct xfrm_user_migrate*)RTA_DATA(rta);
+ old_src = xfrm2host(migrate->old_family, &migrate->old_saddr, 0);
+ old_dst = xfrm2host(migrate->old_family, &migrate->old_daddr, 0);
+ new_src = xfrm2host(migrate->new_family, &migrate->new_saddr, 0);
+ new_dst = xfrm2host(migrate->new_family, &migrate->new_daddr, 0);
+ proto = proto_kernel2ike(migrate->proto);
+ reqid = migrate->reqid;
+ DBG2(DBG_KNL, " migrate %N %H...%H to %H...%H, reqid {%u}",
+ protocol_id_names, proto, old_src, old_dst,
+ new_src, new_dst, reqid);
+ DESTROY_IF(old_src);
+ DESTROY_IF(old_dst);
+ DESTROY_IF(new_src);
+ DESTROY_IF(new_dst);
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ if (src_ts && dst_ts && local && remote)
+ {
+ DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
+ src_ts, dst_ts, policy_dir_names, dir, reqid, local);
+ job = (job_t*)migrate_job_create(reqid, src_ts, dst_ts, dir,
+ local, remote);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ else
+ {
+ DESTROY_IF(src_ts);
+ DESTROY_IF(dst_ts);
+ DESTROY_IF(local);
+ DESTROY_IF(remote);
+ }
+}
+
+/**
+ * process a XFRM_MSG_MAPPING from kernel
+ */
+static void process_mapping(private_kernel_netlink_ipsec_t *this,
+ struct nlmsghdr *hdr)
+{
+ job_t *job;
+ u_int32_t spi, reqid;
+ struct xfrm_user_mapping *mapping;
+ host_t *host;
+
+ mapping = (struct xfrm_user_mapping*)NLMSG_DATA(hdr);
+ spi = mapping->id.spi;
+ reqid = mapping->reqid;
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING");
+
+ if (proto_kernel2ike(mapping->id.proto) == PROTO_ESP)
+ {
+ host = xfrm2host(mapping->id.family, &mapping->new_saddr,
+ mapping->new_sport);
+ if (host)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and "
+ "reqid {%u} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, host);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
+{
+ char response[1024];
+ struct nlmsghdr *hdr = (struct nlmsghdr*)response;
+ struct sockaddr_nl addr;
+ socklen_t addr_len = sizeof(addr);
+ int len;
+ bool oldstate;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->socket_xfrm_events, response, sizeof(response), 0,
+ (struct sockaddr*)&addr, &addr_len);
+ 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 xfrm event socket");
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+ }
+
+ if (addr.nl_pid != 0)
+ { /* not from kernel. not interested, try another one */
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_ACQUIRE:
+ process_acquire(this, hdr);
+ break;
+ case XFRM_MSG_EXPIRE:
+ process_expire(this, hdr);
+ break;
+ case XFRM_MSG_MIGRATE:
+ process_migrate(this, hdr);
+ break;
+ case XFRM_MSG_MAPPING:
+ process_mapping(this, hdr);
+ break;
+ default:
+ DBG1(DBG_KNL, "received unknown event from xfrm event socket: %d", hdr->nlmsg_type);
+ break;
+ }
+ hdr = NLMSG_NEXT(hdr, len);
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Get an SPI for a specific protocol from the kernel.
+ */
+static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
+ host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max,
+ u_int32_t reqid, u_int32_t *spi)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out;
+ struct xfrm_userspi_info *userspi;
+ u_int32_t received_spi = 0;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
+
+ userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr);
+ host2xfrm(src, &userspi->info.saddr);
+ host2xfrm(dst, &userspi->info.id.daddr);
+ userspi->info.id.proto = proto;
+ userspi->info.mode = XFRM_MODE_TUNNEL;
+ userspi->info.reqid = reqid;
+ userspi->info.family = src->get_family(src);
+ userspi->min = min;
+ userspi->max = max;
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWSA:
+ {
+ struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr);
+ received_spi = usersa->id.spi;
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+
+ DBG1(DBG_KNL, "allocating SPI failed: %s (%d)",
+ strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ free(out);
+ }
+
+ if (received_spi == 0)
+ {
+ return FAILED;
+ }
+
+ *spi = received_spi;
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ protocol_id_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, proto_ike2kernel(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_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ 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,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
+ 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 encap, bool inbound, traffic_selector_t* src_ts,
+ traffic_selector_t* dst_ts)
+{
+ netlink_buf_t request;
+ char *alg_name;
+ struct nlmsghdr *hdr;
+ struct xfrm_usersa_info *sa;
+ u_int16_t icv_size = 64;
+
+ /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
+ * we are in the recursive call below */
+ if (ipcomp != IPCOMP_NONE && cpi != 0)
+ {
+ lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
+ add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, &lft,
+ ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+ mode, ipcomp, 0, 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}",
+ ntohl(spi), reqid);
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+
+ sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
+ host2xfrm(src, &sa->saddr);
+ host2xfrm(dst, &sa->id.daddr);
+ sa->id.spi = spi;
+ sa->id.proto = proto_ike2kernel(protocol);
+ sa->family = src->get_family(src);
+ sa->mode = mode2kernel(mode);
+ switch (mode)
+ {
+ case MODE_TUNNEL:
+ sa->flags |= XFRM_STATE_AF_UNSPEC;
+ break;
+ case MODE_BEET:
+ if(src_ts && dst_ts)
+ {
+ sa->sel = ts2selector(src_ts, dst_ts);
+ }
+ break;
+ default:
+ break;
+ }
+
+ sa->replay_window = (protocol == IPPROTO_COMP) ? 0 : 32;
+ sa->reqid = reqid;
+ sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey);
+ sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life);
+ sa->lft.soft_packet_limit = XFRM_LIMIT(lifetime->packets.rekey);
+ sa->lft.hard_packet_limit = XFRM_LIMIT(lifetime->packets.life);
+ /* we use lifetimes since added, not since used */
+ sa->lft.soft_add_expires_seconds = lifetime->time.rekey;
+ sa->lft.hard_add_expires_seconds = lifetime->time.life;
+ sa->lft.soft_use_expires_seconds = 0;
+ sa->lft.hard_use_expires_seconds = 0;
+
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info);
+
+ switch (enc_alg)
+ {
+ case ENCR_UNDEFINED:
+ /* no encryption */
+ break;
+ case ENCR_AES_CCM_ICV16:
+ case ENCR_AES_GCM_ICV16:
+ case ENCR_NULL_AUTH_AES_GMAC:
+ case ENCR_CAMELLIA_CCM_ICV16:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_CAMELLIA_CCM_ICV12:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_CAMELLIA_CCM_ICV8:
+ {
+ struct xfrm_algo_aead *algo;
+
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
+ if (alg_name == NULL)
+ {
+ 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);
+
+ rthdr->rta_type = XFRMA_ALG_AEAD;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len);
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
+ algo->alg_key_len = enc_key.len * 8;
+ algo->alg_icv_len = icv_size;
+ strcpy(algo->alg_name, alg_name);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ break;
+ }
+ default:
+ {
+ struct xfrm_algo *algo;
+
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
+ if (alg_name == NULL)
+ {
+ 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);
+
+ rthdr->rta_type = XFRMA_ALG_CRYPT;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len);
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ algo = (struct xfrm_algo*)RTA_DATA(rthdr);
+ algo->alg_key_len = enc_key.len * 8;
+ strcpy(algo->alg_name, alg_name);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+ }
+
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ alg_name = lookup_algorithm(integrity_algs, int_alg);
+ if (alg_name == NULL)
+ {
+ 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);
+
+ if (int_alg == AUTH_HMAC_SHA2_256_128)
+ {
+ struct xfrm_algo_auth* algo;
+
+ /* the kernel uses SHA256 with 96 bit truncation by default,
+ * use specified truncation size supported by newer kernels */
+ rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + int_key.len);
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr);
+ algo->alg_key_len = int_key.len * 8;
+ algo->alg_trunc_len = 128;
+ strcpy(algo->alg_name, alg_name);
+ memcpy(algo->alg_key, int_key.ptr, int_key.len);
+ }
+ else
+ {
+ struct xfrm_algo* algo;
+
+ rthdr->rta_type = XFRMA_ALG_AUTH;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ algo = (struct xfrm_algo*)RTA_DATA(rthdr);
+ algo->alg_key_len = int_key.len * 8;
+ strcpy(algo->alg_name, alg_name);
+ memcpy(algo->alg_key, int_key.ptr, int_key.len);
+ }
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ rthdr->rta_type = XFRMA_ALG_COMP;
+ alg_name = lookup_algorithm(compression_algs, ipcomp);
+ if (alg_name == NULL)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ ipcomp_transform_names, ipcomp);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using compression algorithm %N",
+ ipcomp_transform_names, ipcomp);
+
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo));
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
+ algo->alg_key_len = 0;
+ strcpy(algo->alg_name, alg_name);
+
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+
+ if (encap)
+ {
+ rthdr->rta_type = XFRMA_ENCAP;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ struct xfrm_encap_tmpl* tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
+ tmpl->encap_type = UDP_ENCAP_ESPINUDP;
+ tmpl->encap_sport = htons(src->get_port(src));
+ tmpl->encap_dport = htons(dst->get_port(dst));
+ memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+ /* encap_oa could probably be derived from the
+ * traffic selectors [rfc4306, p39]. In the netlink kernel implementation
+ * pluto does the same as we do here but it uses encap_oa in the
+ * pfkey implementation. BUT as /usr/src/linux/net/key/af_key.c indicates
+ * the kernel ignores it anyway
+ * -> does that mean that NAT-T encap doesn't work in transport mode?
+ * No. The reason the kernel ignores NAT-OA is that it recomputes
+ * (or, rather, just ignores) the checksum. If packets pass
+ * the IPsec checks it marks them "checksum ok" so OA isn't needed. */
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Get the replay state (i.e. sequence numbers) of an SA.
+ */
+static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, host_t *dst,
+ struct xfrm_replay_state *replay)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out = NULL;
+ struct xfrm_aevent_id *out_aevent = NULL, *aevent_id;
+ size_t len;
+ struct rtattr *rta;
+ size_t rtasize;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x", ntohl(spi));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETAE;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
+
+ aevent_id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
+ aevent_id->flags = XFRM_AE_RVAL;
+
+ host2xfrm(dst, &aevent_id->sa_id.daddr);
+ aevent_id->sa_id.spi = spi;
+ aevent_id->sa_id.proto = proto_ike2kernel(protocol);
+ aevent_id->sa_id.family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWAE:
+ {
+ out_aevent = NLMSG_DATA(hdr);
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "querying replay state from SAD entry failed: %s (%d)",
+ strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ }
+
+ if (out_aevent == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI %.8x",
+ ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+
+ rta = XFRM_RTA(out, struct xfrm_aevent_id);
+ rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id);
+ while(RTA_OK(rta, rtasize))
+ {
+ if (rta->rta_type == XFRMA_REPLAY_VAL &&
+ RTA_PAYLOAD(rta) == sizeof(struct xfrm_replay_state))
+ {
+ memcpy(replay, RTA_DATA(rta), RTA_PAYLOAD(rta));
+ free(out);
+ return SUCCESS;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI %.8x",
+ ntohl(spi));
+ free(out);
+ return FAILED;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *out = NULL, *hdr;
+ struct xfrm_usersa_id *sa_id;
+ struct xfrm_usersa_info *sa = NULL;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+ sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ host2xfrm(dst, &sa_id->daddr);
+ sa_id->spi = spi;
+ sa_id->proto = proto_ike2kernel(protocol);
+ sa_id->family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWSA:
+ {
+ sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)",
+ ntohl(spi), strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ }
+
+ if (sa == NULL)
+ {
+ DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+ *bytes = sa->curlft.bytes;
+
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct xfrm_usersa_id *sa_id;
+
+ /* if IPComp was used, we first delete the additional IPComp SA */
+ if (cpi)
+ {
+ del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0);
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = XFRM_MSG_DELSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+ sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ host2xfrm(dst, &sa_id->daddr);
+ sa_id->spi = spi;
+ sa_id->proto = proto_ike2kernel(protocol);
+ sa_id->family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+ private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool old_encap, bool new_encap)
+{
+ netlink_buf_t request;
+ u_char *pos;
+ struct nlmsghdr *hdr, *out = NULL;
+ struct xfrm_usersa_id *sa_id;
+ struct xfrm_usersa_info *out_sa = NULL, *sa;
+ size_t len;
+ struct rtattr *rta;
+ size_t rtasize;
+ struct xfrm_encap_tmpl* tmpl = NULL;
+ bool got_replay_state = FALSE;
+ struct xfrm_replay_state replay;
+
+ /* if IPComp is used, we first update the IPComp SA */
+ if (cpi)
+ {
+ update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
+ src, dst, new_src, new_dst, FALSE, FALSE);
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
+
+ /* query the existing SA first */
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+ sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ host2xfrm(dst, &sa_id->daddr);
+ sa_id->spi = spi;
+ sa_id->proto = proto_ike2kernel(protocol);
+ sa_id->family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWSA:
+ {
+ out_sa = NLMSG_DATA(hdr);
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "querying SAD entry failed: %s (%d)",
+ strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ }
+ if (out_sa == NULL)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+
+ /* try to get the replay state */
+ if (get_replay_state(this, spi, protocol, dst, &replay) == SUCCESS)
+ {
+ got_replay_state = TRUE;
+ }
+
+ /* delete the old SA (without affecting the IPComp SA) */
+ if (del_sa(this, src, dst, spi, protocol, 0) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+ /* copy over the SA from out to request */
+ hdr = (struct nlmsghdr*)request;
+ memcpy(hdr, out, min(out->nlmsg_len, sizeof(request)));
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = XFRM_MSG_NEWSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+ sa = NLMSG_DATA(hdr);
+ sa->family = new_dst->get_family(new_dst);
+
+ if (!src->ip_equals(src, new_src))
+ {
+ host2xfrm(new_src, &sa->saddr);
+ }
+ if (!dst->ip_equals(dst, new_dst))
+ {
+ host2xfrm(new_dst, &sa->id.daddr);
+ }
+
+ rta = XFRM_RTA(out, struct xfrm_usersa_info);
+ rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
+ pos = (u_char*)XFRM_RTA(hdr, struct xfrm_usersa_info);
+ while(RTA_OK(rta, rtasize))
+ {
+ /* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
+ if (rta->rta_type != XFRMA_ENCAP || new_encap)
+ {
+ if (rta->rta_type == XFRMA_ENCAP)
+ { /* update encap tmpl */
+ tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta);
+ tmpl->encap_sport = ntohs(new_src->get_port(new_src));
+ tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+ }
+ memcpy(pos, rta, rta->rta_len);
+ pos += RTA_ALIGN(rta->rta_len);
+ hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ rta = (struct rtattr*)pos;
+ if (tmpl == NULL && new_encap)
+ { /* add tmpl if we are enabling it */
+ rta->rta_type = XFRMA_ENCAP;
+ rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
+
+ hdr->nlmsg_len += rta->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta);
+ tmpl->encap_type = UDP_ENCAP_ESPINUDP;
+ tmpl->encap_sport = ntohs(new_src->get_port(new_src));
+ tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+ memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+
+ rta = XFRM_RTA_NEXT(rta);
+ }
+
+ if (got_replay_state)
+ { /* copy the replay data if available */
+ rta->rta_type = XFRMA_REPLAY_VAL;
+ rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
+
+ hdr->nlmsg_len += rta->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+ memcpy(RTA_DATA(rta), &replay, sizeof(replay));
+
+ rta = XFRM_RTA_NEXT(rta);
+ }
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ policy_entry_t *current, *policy;
+ bool found = FALSE;
+ netlink_buf_t request;
+ struct xfrm_userpolicy_info *policy_info;
+ struct nlmsghdr *hdr;
+
+ /* create a policy */
+ policy = malloc_thing(policy_entry_t);
+ memset(policy, 0, sizeof(policy_entry_t));
+ policy->sel = ts2selector(src_ts, dst_ts);
+ policy->direction = direction;
+
+ /* find the policy, which matches EXACTLY */
+ this->mutex->lock(this->mutex);
+ current = this->policies->get(this->policies, policy);
+ if (current)
+ {
+ /* use existing policy */
+ current->refcount++;
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
+ "refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ free(policy);
+ policy = current;
+ found = TRUE;
+ }
+ else
+ { /* apply the new one, if we have no such policy */
+ this->policies->put(this->policies, policy, policy);
+ policy->refcount = 1;
+ }
+
+ DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ memset(&request, 0, sizeof(request));
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = found ? XFRM_MSG_UPDPOLICY : XFRM_MSG_NEWPOLICY;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
+
+ policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
+ policy_info->sel = policy->sel;
+ policy_info->dir = policy->direction;
+ /* calculate priority based on source selector size, small size = high prio */
+ policy_info->priority = routed ? PRIO_LOW : PRIO_HIGH;
+ policy_info->priority -= policy->sel.prefixlen_s * 10;
+ policy_info->priority -= policy->sel.proto ? 2 : 0;
+ policy_info->priority -= policy->sel.sport_mask ? 1 : 0;
+ policy_info->action = XFRM_POLICY_ALLOW;
+ policy_info->share = XFRM_SHARE_ANY;
+ this->mutex->unlock(this->mutex);
+
+ /* policies don't expire */
+ policy_info->lft.soft_byte_limit = XFRM_INF;
+ policy_info->lft.soft_packet_limit = XFRM_INF;
+ policy_info->lft.hard_byte_limit = XFRM_INF;
+ policy_info->lft.hard_packet_limit = XFRM_INF;
+ policy_info->lft.soft_add_expires_seconds = 0;
+ policy_info->lft.hard_add_expires_seconds = 0;
+ policy_info->lft.soft_use_expires_seconds = 0;
+ policy_info->lft.hard_use_expires_seconds = 0;
+
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
+ rthdr->rta_type = XFRMA_TMPL;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ tmpl->reqid = reqid;
+ tmpl->id.proto = IPPROTO_COMP;
+ tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
+ tmpl->mode = mode2kernel(mode);
+ tmpl->optional = direction != POLICY_OUT;
+ tmpl->family = src->get_family(src);
+
+ host2xfrm(src, &tmpl->saddr);
+ host2xfrm(dst, &tmpl->id.daddr);
+
+ /* add an additional xfrm_user_tmpl */
+ rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+ hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ tmpl++;
+
+ /* use transport mode for ESP if we have a tunnel mode IPcomp SA */
+ mode = MODE_TRANSPORT;
+ }
+ else
+ {
+ /* when using IPcomp, only the IPcomp SA uses tmp src/dst addresses */
+ host2xfrm(src, &tmpl->saddr);
+ host2xfrm(dst, &tmpl->id.daddr);
+ }
+
+ tmpl->reqid = reqid;
+ tmpl->id.proto = proto_ike2kernel(protocol);
+ tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
+ tmpl->mode = mode2kernel(mode);
+ tmpl->family = src->get_family(src);
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+
+ /* install a route, if:
+ * - we are NOT updating a policy
+ * - this is a forward policy (to just get one for each child)
+ * - we are in tunnel/BEET mode
+ * - routing is not disabled via strongswan.conf
+ */
+ if (policy->route == NULL && direction == POLICY_FWD &&
+ mode != MODE_TRANSPORT && this->install_routes)
+ {
+ route_entry_t *route = malloc_thing(route_entry_t);
+
+ if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ dst_ts, &route->src_ip) == SUCCESS)
+ {
+ /* get the nexthop to src (src as we are in POLICY_FWD).*/
+ route->gateway = charon->kernel_interface->get_nexthop(
+ charon->kernel_interface, src);
+ /* install route via outgoing interface */
+ route->if_name = charon->kernel_interface->get_interface(
+ charon->kernel_interface, dst);
+ route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
+ memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len);
+ route->prefixlen = policy->sel.prefixlen_s;
+
+ if (route->if_name)
+ {
+ switch (charon->kernel_interface->add_route(
+ charon->kernel_interface, route->dst_net,
+ route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install source route for %H",
+ route->src_ip);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+ else
+ {
+ route_entry_destroy(route);
+ }
+ }
+ else
+ {
+ free(route);
+ }
+ }
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+ private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *out = NULL, *hdr;
+ struct xfrm_userpolicy_id *policy_id;
+ struct xfrm_userpolicy_info *policy = NULL;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+ policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ policy_id->sel = ts2selector(src_ts, dst_ts);
+ policy_id->dir = direction;
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWPOLICY:
+ {
+ policy = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "querying policy failed: %s (%d)",
+ strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ }
+
+ if (policy == NULL)
+ {
+ DBG2(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+
+ if (policy->curlft.use_time)
+ {
+ /* we need the monotonic time, but the kernel returns system time. */
+ *use_time = time_monotonic(NULL) - (time(NULL) - policy->curlft.use_time);
+ }
+ else
+ {
+ *use_time = 0;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+ private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+{
+ policy_entry_t *current, policy, *to_delete = NULL;
+ route_entry_t *route;
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct xfrm_userpolicy_id *policy_id;
+
+ DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ memset(&policy, 0, sizeof(policy_entry_t));
+ policy.sel = ts2selector(src_ts, dst_ts);
+ policy.direction = direction;
+
+ /* find the policy */
+ this->mutex->lock(this->mutex);
+ current = this->policies->get(this->policies, &policy);
+ if (current)
+ {
+ to_delete = current;
+ if (--to_delete->refcount > 0)
+ {
+ /* is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ /* remove if last reference */
+ this->policies->remove(this->policies, to_delete);
+ }
+ this->mutex->unlock(this->mutex);
+ if (!to_delete)
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ return NOT_FOUND;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = XFRM_MSG_DELPOLICY;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+ policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ policy_id->sel = to_delete->sel;
+ policy_id->dir = direction;
+
+ route = to_delete->route;
+ free(to_delete);
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+
+ if (route)
+ {
+ if (charon->kernel_interface->del_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "error uninstalling route installed with "
+ "policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
+ route_entry_destroy(route);
+ }
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_netlink_ipsec_t *this, int fd, int family)
+{
+ struct xfrm_userpolicy_info policy;
+ u_int sol, ipsec_policy;
+
+ switch (family)
+ {
+ case AF_INET:
+ sol = SOL_IP;
+ ipsec_policy = IP_XFRM_POLICY;
+ break;
+ case AF_INET6:
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_XFRM_POLICY;
+ break;
+ default:
+ return FALSE;
+ }
+
+ memset(&policy, 0, sizeof(policy));
+ policy.action = XFRM_POLICY_ALLOW;
+ policy.sel.family = family;
+
+ policy.dir = XFRM_POLICY_OUT;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ policy.dir = XFRM_POLICY_IN;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_netlink_ipsec_t *this)
+{
+ enumerator_t *enumerator;
+ policy_entry_t *policy;
+
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ if (this->socket_xfrm_events > 0)
+ {
+ close(this->socket_xfrm_events);
+ }
+ DESTROY_IF(this->socket_xfrm);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, &policy, &policy))
+ {
+ free(policy);
+ }
+ enumerator->destroy(enumerator);
+ this->policies->destroy(this->policies);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
+{
+ private_kernel_netlink_ipsec_t *this;
+ struct sockaddr_nl addr;
+ int fd;
+
+ 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,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
+ .destroy = _destroy,
+ },
+ .policies = hashtable_create((hashtable_hash_t)policy_hash,
+ (hashtable_equals_t)policy_equals, 32),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .install_routes = lib->settings->get_bool(lib->settings,
+ "charon.install_routes", TRUE),
+ );
+
+ /* disable lifetimes for allocated SPIs in kernel */
+ fd = open("/proc/sys/net/core/xfrm_acq_expires", O_WRONLY);
+ if (fd)
+ {
+ ignore_result(write(fd, "165", 3));
+ close(fd);
+ }
+
+ this->socket_xfrm = netlink_socket_create(NETLINK_XFRM);
+ if (!this->socket_xfrm)
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+
+ /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
+ this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
+ if (this->socket_xfrm_events <= 0)
+ {
+ DBG1(DBG_KNL, "unable to create XFRM event socket");
+ destroy(this);
+ return NULL;
+ }
+ addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
+ XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
+ if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ DBG1(DBG_KNL, "unable to bind XFRM event socket");
+ destroy(this);
+ return NULL;
+ }
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h
new file mode 100644
index 000000000..3a45cce06
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_netlink_ipsec_i kernel_netlink_ipsec
+ * @{ @ingroup kernel_netlink
+ */
+
+#ifndef KERNEL_NETLINK_IPSEC_H_
+#define KERNEL_NETLINK_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_netlink_ipsec_t kernel_netlink_ipsec_t;
+
+/**
+ * Implementation of the kernel ipsec interface using Netlink.
+ */
+struct kernel_netlink_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a netlink kernel ipsec interface instance.
+ *
+ * @return kernel_netlink_ipsec_t instance
+ */
+kernel_netlink_ipsec_t *kernel_netlink_ipsec_create();
+
+#endif /** KERNEL_NETLINK_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
new file mode 100644
index 000000000..6750458cf
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -0,0 +1,1506 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/if.h>
+
+#include "kernel_netlink_net.h"
+#include "kernel_netlink_shared.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/roam_job.h>
+
+/** delay before firing roam jobs (ms) */
+#define ROAM_DELAY 100
+
+typedef struct addr_entry_t addr_entry_t;
+
+/**
+ * IP address in an inface_entry_t
+ */
+struct addr_entry_t {
+
+ /** The ip address */
+ host_t *ip;
+
+ /** virtual IP managed by us */
+ bool virtual;
+
+ /** scope of the address */
+ u_char scope;
+
+ /** Number of times this IP is used, if virtual */
+ u_int refcount;
+};
+
+/**
+ * destroy a addr_entry_t object
+ */
+static void addr_entry_destroy(addr_entry_t *this)
+{
+ this->ip->destroy(this->ip);
+ free(this);
+}
+
+typedef struct iface_entry_t iface_entry_t;
+
+/**
+ * A network interface on this system, containing addr_entry_t's
+ */
+struct iface_entry_t {
+
+ /** interface index */
+ int ifindex;
+
+ /** name of the interface */
+ char ifname[IFNAMSIZ];
+
+ /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
+ u_int flags;
+
+ /** list of addresses as host_t */
+ linked_list_t *addrs;
+};
+
+/**
+ * destroy an interface entry
+ */
+static void iface_entry_destroy(iface_entry_t *this)
+{
+ this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
+ free(this);
+}
+
+typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
+
+/**
+ * Private variables and functions of kernel_netlink_net class.
+ */
+struct private_kernel_netlink_net_t {
+ /**
+ * Public part of the kernel_netlink_net_t object.
+ */
+ kernel_netlink_net_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * condition variable to signal virtual IP add/removal
+ */
+ condvar_t *condvar;
+
+ /**
+ * Cached list of interfaces and its addresses (iface_entry_t)
+ */
+ linked_list_t *ifaces;
+
+ /**
+ * job receiving netlink events
+ */
+ callback_job_t *job;
+
+ /**
+ * netlink rt socket (routing)
+ */
+ netlink_socket_t *socket;
+
+ /**
+ * Netlink rt socket to receive address change events
+ */
+ int socket_events;
+
+ /**
+ * time of the last roam_job
+ */
+ timeval_t last_roam;
+
+ /**
+ * routing table to install routes
+ */
+ int routing_table;
+
+ /**
+ * priority of used routing table
+ */
+ int routing_table_prio;
+
+ /**
+ * whether to react to RTM_NEWROUTE or RTM_DELROUTE events
+ */
+ bool process_route;
+
+ /**
+ * whether to actually install virtual IPs
+ */
+ bool install_virtual_ip;
+
+ /**
+ * list with routing tables to be excluded from route lookup
+ */
+ linked_list_t *rt_exclude;
+};
+
+/**
+ * get the refcount of a virtual ip
+ */
+static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
+{
+ iterator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ int refcount = 0;
+
+ ifaces = this->ifaces->create_iterator(this->ifaces, TRUE);
+ while (ifaces->iterate(ifaces, (void**)&iface))
+ {
+ addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
+ while (addrs->iterate(addrs, (void**)&addr))
+ {
+ if (addr->virtual && (iface->flags & IFF_UP) &&
+ ip->ip_equals(ip, addr->ip))
+ {
+ refcount = addr->refcount;
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+ if (refcount)
+ {
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+
+ return refcount;
+}
+
+/**
+ * start a roaming job. We delay it for a second and fire only one job
+ * for multiple events. Otherwise we would create two many jobs.
+ */
+static void fire_roam_job(private_kernel_netlink_net_t *this, bool address)
+{
+ timeval_t now;
+
+ time_monotonic(&now);
+ if (timercmp(&now, &this->last_roam, >))
+ {
+ now.tv_usec += ROAM_DELAY * 1000;
+ while (now.tv_usec > 1000000)
+ {
+ now.tv_sec++;
+ now.tv_usec -= 1000000;
+ }
+ this->last_roam = now;
+ charon->scheduler->schedule_job_ms(charon->scheduler,
+ (job_t*)roam_job_create(address), ROAM_DELAY);
+ }
+}
+
+/**
+ * process RTM_NEWLINK/RTM_DELLINK from kernel
+ */
+static void process_link(private_kernel_netlink_net_t *this,
+ struct nlmsghdr *hdr, bool event)
+{
+ struct ifinfomsg* msg = (struct ifinfomsg*)(NLMSG_DATA(hdr));
+ struct rtattr *rta = IFLA_RTA(msg);
+ size_t rtasize = IFLA_PAYLOAD (hdr);
+ enumerator_t *enumerator;
+ iface_entry_t *current, *entry = NULL;
+ char *name = NULL;
+ bool update = FALSE;
+
+ while(RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case IFLA_IFNAME:
+ name = RTA_DATA(rta);
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ if (!name)
+ {
+ name = "(unknown)";
+ }
+
+ this->mutex->lock(this->mutex);
+ switch (hdr->nlmsg_type)
+ {
+ case RTM_NEWLINK:
+ {
+ if (msg->ifi_flags & IFF_LOOPBACK)
+ { /* ignore loopback interfaces */
+ break;
+ }
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->ifindex == msg->ifi_index)
+ {
+ entry = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!entry)
+ {
+ entry = malloc_thing(iface_entry_t);
+ entry->ifindex = msg->ifi_index;
+ entry->flags = 0;
+ entry->addrs = linked_list_create();
+ this->ifaces->insert_last(this->ifaces, entry);
+ }
+ memcpy(entry->ifname, name, IFNAMSIZ);
+ entry->ifname[IFNAMSIZ-1] = '\0';
+ if (event)
+ {
+ if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
+ {
+ update = TRUE;
+ DBG1(DBG_KNL, "interface %s activated", name);
+ }
+ if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
+ {
+ update = TRUE;
+ DBG1(DBG_KNL, "interface %s deactivated", name);
+ }
+ }
+ entry->flags = msg->ifi_flags;
+ break;
+ }
+ case RTM_DELLINK:
+ {
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->ifindex == msg->ifi_index)
+ {
+ /* we do not remove it, as an address may be added to a
+ * "down" interface and we wan't to know that. */
+ current->flags = msg->ifi_flags;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ break;
+ }
+ }
+ this->mutex->unlock(this->mutex);
+
+ /* send an update to all IKE_SAs */
+ if (update && event)
+ {
+ fire_roam_job(this, TRUE);
+ }
+}
+
+/**
+ * process RTM_NEWADDR/RTM_DELADDR from kernel
+ */
+static void process_addr(private_kernel_netlink_net_t *this,
+ struct nlmsghdr *hdr, bool event)
+{
+ struct ifaddrmsg* msg = (struct ifaddrmsg*)(NLMSG_DATA(hdr));
+ struct rtattr *rta = IFA_RTA(msg);
+ size_t rtasize = IFA_PAYLOAD (hdr);
+ host_t *host = NULL;
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ chunk_t local = chunk_empty, address = chunk_empty;
+ bool update = FALSE, found = FALSE, changed = FALSE;
+
+ while(RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case IFA_LOCAL:
+ local.ptr = RTA_DATA(rta);
+ local.len = RTA_PAYLOAD(rta);
+ break;
+ case IFA_ADDRESS:
+ address.ptr = RTA_DATA(rta);
+ address.len = RTA_PAYLOAD(rta);
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ /* For PPP interfaces, we need the IFA_LOCAL address,
+ * IFA_ADDRESS is the peers address. But IFA_LOCAL is
+ * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
+ if (local.ptr)
+ {
+ host = host_create_from_chunk(msg->ifa_family, local, 0);
+ }
+ else if (address.ptr)
+ {
+ host = host_create_from_chunk(msg->ifa_family, address, 0);
+ }
+
+ if (host == NULL)
+ { /* bad family? */
+ return;
+ }
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == msg->ifa_index)
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (host->ip_equals(host, addr->ip))
+ {
+ found = TRUE;
+ if (hdr->nlmsg_type == RTM_DELADDR)
+ {
+ iface->addrs->remove_at(iface->addrs, addrs);
+ if (!addr->virtual)
+ {
+ changed = TRUE;
+ DBG1(DBG_KNL, "%H disappeared from %s",
+ host, iface->ifname);
+ }
+ addr_entry_destroy(addr);
+ }
+ else if (hdr->nlmsg_type == RTM_NEWADDR && addr->virtual)
+ {
+ addr->refcount = 1;
+ }
+ }
+ }
+ addrs->destroy(addrs);
+
+ if (hdr->nlmsg_type == RTM_NEWADDR)
+ {
+ if (!found)
+ {
+ found = TRUE;
+ changed = TRUE;
+ addr = malloc_thing(addr_entry_t);
+ addr->ip = host->clone(host);
+ addr->virtual = FALSE;
+ addr->refcount = 1;
+ addr->scope = msg->ifa_scope;
+
+ iface->addrs->insert_last(iface->addrs, addr);
+ if (event)
+ {
+ DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+ }
+ }
+ }
+ if (found && (iface->flags & IFF_UP))
+ {
+ update = TRUE;
+ }
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ host->destroy(host);
+
+ /* send an update to all IKE_SAs */
+ if (update && event && changed)
+ {
+ fire_roam_job(this, TRUE);
+ }
+}
+
+/**
+ * process RTM_NEWROUTE and RTM_DELROUTE from kernel
+ */
+static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
+{
+ struct rtmsg* msg = (struct rtmsg*)(NLMSG_DATA(hdr));
+ struct rtattr *rta = RTM_RTA(msg);
+ size_t rtasize = RTM_PAYLOAD(hdr);
+ host_t *host = NULL;
+
+ /* ignore routes added by us */
+ if (msg->rtm_table && msg->rtm_table == this->routing_table)
+ {
+ return;
+ }
+
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case RTA_PREFSRC:
+ host = host_create_from_chunk(msg->rtm_family,
+ chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ if (host)
+ {
+ this->mutex->lock(this->mutex);
+ if (!get_vip_refcount(this, host))
+ { /* ignore routes added for virtual IPs */
+ fire_roam_job(this, FALSE);
+ }
+ this->mutex->unlock(this->mutex);
+ host->destroy(host);
+ }
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
+{
+ char response[1024];
+ struct nlmsghdr *hdr = (struct nlmsghdr*)response;
+ struct sockaddr_nl addr;
+ socklen_t addr_len = sizeof(addr);
+ int len;
+ bool oldstate;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->socket_events, response, sizeof(response), 0,
+ (struct sockaddr*)&addr, &addr_len);
+ 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 rt event socket");
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+ }
+
+ if (addr.nl_pid != 0)
+ { /* not from kernel. not interested, try another one */
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ while (NLMSG_OK(hdr, len))
+ {
+ /* looks good so far, dispatch netlink message */
+ switch (hdr->nlmsg_type)
+ {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ process_addr(this, hdr, TRUE);
+ this->condvar->broadcast(this->condvar);
+ break;
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ process_link(this, hdr, TRUE);
+ this->condvar->broadcast(this->condvar);
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ if (this->process_route)
+ {
+ process_route(this, hdr);
+ }
+ break;
+ default:
+ break;
+ }
+ hdr = NLMSG_NEXT(hdr, len);
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+/** enumerator over addresses */
+typedef struct {
+ private_kernel_netlink_net_t* this;
+ /** whether to enumerate down interfaces */
+ bool include_down_ifaces;
+ /** whether to enumerate virtual ip addresses */
+ bool include_virtual_ips;
+} address_enumerator_t;
+
+/**
+ * cleanup function for address enumerator
+ */
+static void address_enumerator_destroy(address_enumerator_t *data)
+{
+ data->this->mutex->unlock(data->this->mutex);
+ free(data);
+}
+
+/**
+ * filter for addresses
+ */
+static bool filter_addresses(address_enumerator_t *data, addr_entry_t** in, host_t** out)
+{
+ if (!data->include_virtual_ips && (*in)->virtual)
+ { /* skip virtual interfaces added by us */
+ return FALSE;
+ }
+ if ((*in)->scope >= RT_SCOPE_LINK)
+ { /* skip addresses with a unusable scope */
+ return FALSE;
+ }
+ *out = (*in)->ip;
+ return TRUE;
+}
+
+/**
+ * enumerator constructor for interfaces
+ */
+static enumerator_t *create_iface_enumerator(iface_entry_t *iface, address_enumerator_t *data)
+{
+ return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
+ (void*)filter_addresses, data, NULL);
+}
+
+/**
+ * filter for interfaces
+ */
+static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out)
+{
+ if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
+ { /* skip interfaces not up */
+ return FALSE;
+ }
+ *out = *in;
+ return TRUE;
+}
+
+/**
+ * implementation of kernel_net_t.create_address_enumerator
+ */
+static enumerator_t *create_address_enumerator(private_kernel_netlink_net_t *this,
+ bool include_down_ifaces, bool include_virtual_ips)
+{
+ address_enumerator_t *data = malloc_thing(address_enumerator_t);
+ data->this = this;
+ data->include_down_ifaces = include_down_ifaces;
+ data->include_virtual_ips = include_virtual_ips;
+
+ this->mutex->lock(this->mutex);
+ return enumerator_create_nested(
+ enumerator_create_filter(this->ifaces->create_enumerator(this->ifaces),
+ (void*)filter_interfaces, data, NULL),
+ (void*)create_iface_enumerator, data, (void*)address_enumerator_destroy);
+}
+
+/**
+ * implementation of kernel_net_t.get_interface_name
+ */
+static char *get_interface_name(private_kernel_netlink_net_t *this, host_t* ip)
+{
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ char *name = NULL;
+
+ DBG2(DBG_KNL, "getting interface name for %H", ip);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (ip->ip_equals(ip, addr->ip))
+ {
+ name = strdup(iface->ifname);
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+ if (name)
+ {
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+
+ if (name)
+ {
+ DBG2(DBG_KNL, "%H is on interface %s", ip, name);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "%H is not a local address", ip);
+ }
+ return name;
+}
+
+/**
+ * get the index of an interface by name
+ */
+static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
+{
+ enumerator_t *ifaces;
+ iface_entry_t *iface;
+ int ifindex = 0;
+
+ DBG2(DBG_KNL, "getting iface index for %s", name);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (streq(name, iface->ifname))
+ {
+ ifindex = iface->ifindex;
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+
+ if (ifindex == 0)
+ {
+ DBG1(DBG_KNL, "unable to get interface index for %s", name);
+ }
+ return ifindex;
+}
+
+/**
+ * Check if an interface with a given index is up
+ */
+static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
+{
+ enumerator_t *ifaces;
+ iface_entry_t *iface;
+ /* default to TRUE for interface we do not monitor (e.g. lo) */
+ bool up = TRUE;
+
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == index)
+ {
+ up = iface->flags & IFF_UP;
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ return up;
+}
+
+/**
+ * check if an address (chunk) addr is in subnet (net with net_len net bits)
+ */
+static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
+{
+ static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+ int byte = 0;
+
+ if (net_len == 0)
+ { /* any address matches a /0 network */
+ return TRUE;
+ }
+ if (addr.len != net.len || net_len > 8 * net.len )
+ {
+ return FALSE;
+ }
+ /* scan through all bytes in network order */
+ while (net_len > 0)
+ {
+ if (net_len < 8)
+ {
+ return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]);
+ }
+ else
+ {
+ if (addr.ptr[byte] != net.ptr[byte])
+ {
+ return FALSE;
+ }
+ byte++;
+ net_len -= 8;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * 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)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out, *current;
+ struct rtmsg *msg;
+ chunk_t chunk;
+ size_t len;
+ int best = -1;
+ enumerator_t *enumerator;
+ host_t *src = NULL, *gtw = NULL;
+
+ DBG2(DBG_KNL, "getting address to reach %H", dest);
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ if (dest->get_family(dest) == AF_INET)
+ {
+ /* We dump all addresses for IPv4, as we want to ignore IPsec specific
+ * routes installed by us. But the kernel does not return source
+ * addresses in a IPv6 dump, so fall back to get() for v6 routes. */
+ hdr->nlmsg_flags |= NLM_F_ROOT | NLM_F_DUMP;
+ }
+ hdr->nlmsg_type = RTM_GETROUTE;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+ msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg->rtm_family = dest->get_family(dest);
+ 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 (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "getting address to %H failed", dest);
+ return NULL;
+ }
+ this->mutex->lock(this->mutex);
+
+ for (current = out; NLMSG_OK(current, len);
+ current = NLMSG_NEXT(current, len))
+ {
+ switch (current->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ break;
+ case RTM_NEWROUTE:
+ {
+ struct rtattr *rta;
+ size_t rtasize;
+ chunk_t rta_gtw, rta_src, rta_dst;
+ u_int32_t rta_oif = 0;
+ host_t *new_src, *new_gtw;
+ bool cont = FALSE;
+ uintptr_t table;
+
+ rta_gtw = rta_src = rta_dst = chunk_empty;
+ msg = (struct rtmsg*)(NLMSG_DATA(current));
+ rta = RTM_RTA(msg);
+ rtasize = RTM_PAYLOAD(current);
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case RTA_PREFSRC:
+ rta_src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_GATEWAY:
+ rta_gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_DST:
+ rta_dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_OIF:
+ if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
+ {
+ rta_oif = *(u_int32_t*)RTA_DATA(rta);
+ }
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ if (msg->rtm_dst_len <= best)
+ { /* not better than a previous one */
+ continue;
+ }
+ enumerator = this->rt_exclude->create_enumerator(this->rt_exclude);
+ while (enumerator->enumerate(enumerator, &table))
+ {
+ if (table == msg->rtm_table)
+ {
+ cont = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (cont)
+ {
+ continue;
+ }
+ if (this->routing_table != 0 &&
+ msg->rtm_table == this->routing_table)
+ { /* route is from our own ipsec routing table */
+ continue;
+ }
+ if (rta_oif && !is_interface_up(this, rta_oif))
+ { /* interface is down */
+ continue;
+ }
+ if (!addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))
+ { /* route destination does not contain dest */
+ continue;
+ }
+
+ if (nexthop)
+ {
+ /* nexthop lookup, return gateway if any */
+ DESTROY_IF(gtw);
+ gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
+ best = msg->rtm_dst_len;
+ continue;
+ }
+ if (rta_src.ptr)
+ {
+ /* got a source address */
+ new_src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
+ if (new_src)
+ {
+ if (get_vip_refcount(this, new_src))
+ { /* skip source address if it is installed by us */
+ new_src->destroy(new_src);
+ }
+ else
+ {
+ DESTROY_IF(src);
+ src = new_src;
+ best = msg->rtm_dst_len;
+ }
+ }
+ continue;
+ }
+ if (rta_gtw.ptr)
+ { /* no source, but a gateway. Lookup source to reach gtw. */
+ new_gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
+ new_src = get_route(this, new_gtw, FALSE, candidate);
+ new_gtw->destroy(new_gtw);
+ if (new_src)
+ {
+ DESTROY_IF(src);
+ src = new_src;
+ best = msg->rtm_dst_len;
+ }
+ continue;
+ }
+ continue;
+ }
+ default:
+ continue;
+ }
+ break;
+ }
+ free(out);
+ this->mutex->unlock(this->mutex);
+
+ if (nexthop)
+ {
+ if (gtw)
+ {
+ return gtw;
+ }
+ return dest->clone(dest);
+ }
+ return src;
+}
+
+/**
+ * Implementation of kernel_net_t.get_source_addr.
+ */
+static host_t* get_source_addr(private_kernel_netlink_net_t *this,
+ host_t *dest, host_t *src)
+{
+ return get_route(this, dest, FALSE, src);
+}
+
+/**
+ * Implementation of kernel_net_t.get_nexthop.
+ */
+static host_t* get_nexthop(private_kernel_netlink_net_t *this, host_t *dest)
+{
+ return get_route(this, dest, TRUE, NULL);
+}
+
+/**
+ * Manages the creation and deletion of ip addresses on an interface.
+ * By setting the appropriate nlmsg_type, the ip will be set or unset.
+ */
+static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
+ int flags, int if_index, host_t *ip)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct ifaddrmsg *msg;
+ chunk_t chunk;
+
+ memset(&request, 0, sizeof(request));
+
+ chunk = ip->get_address(ip);
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
+ hdr->nlmsg_type = nlmsg_type;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+
+ msg = (struct ifaddrmsg*)NLMSG_DATA(hdr);
+ msg->ifa_family = ip->get_family(ip);
+ msg->ifa_flags = 0;
+ msg->ifa_prefixlen = 8 * chunk.len;
+ msg->ifa_scope = RT_SCOPE_UNIVERSE;
+ msg->ifa_index = if_index;
+
+ netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
+
+ return this->socket->send_ack(this->socket, hdr);
+}
+
+/**
+ * Implementation of kernel_net_t.add_ip.
+ */
+static status_t add_ip(private_kernel_netlink_net_t *this,
+ host_t *virtual_ip, host_t *iface_ip)
+{
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ enumerator_t *addrs, *ifaces;
+ int ifindex;
+
+ if (!this->install_virtual_ip)
+ { /* disabled by config */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ bool iface_found = FALSE;
+
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (iface_ip->ip_equals(iface_ip, addr->ip))
+ {
+ iface_found = TRUE;
+ }
+ else if (virtual_ip->ip_equals(virtual_ip, addr->ip))
+ {
+ addr->refcount++;
+ DBG2(DBG_KNL, "virtual IP %H already installed on %s",
+ virtual_ip, iface->ifname);
+ addrs->destroy(addrs);
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ }
+ addrs->destroy(addrs);
+
+ if (iface_found)
+ {
+ ifindex = iface->ifindex;
+ addr = malloc_thing(addr_entry_t);
+ addr->ip = virtual_ip->clone(virtual_ip);
+ addr->refcount = 0;
+ addr->virtual = TRUE;
+ addr->scope = RT_SCOPE_UNIVERSE;
+ iface->addrs->insert_last(iface->addrs, addr);
+
+ if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
+ ifindex, virtual_ip) == SUCCESS)
+ {
+ while (get_vip_refcount(this, virtual_ip) == 0)
+ { /* wait until address appears */
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
+ return FAILED;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+
+ DBG1(DBG_KNL, "interface address %H not found, unable to install"
+ "virtual IP %H", iface_ip, virtual_ip);
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_net_t.del_ip.
+ */
+static status_t del_ip(private_kernel_netlink_net_t *this, host_t *virtual_ip)
+{
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ enumerator_t *addrs, *ifaces;
+ status_t status;
+ int ifindex;
+
+ if (!this->install_virtual_ip)
+ { /* disabled by config */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (virtual_ip->ip_equals(virtual_ip, addr->ip))
+ {
+ ifindex = iface->ifindex;
+ if (addr->refcount == 1)
+ {
+ status = manage_ipaddr(this, RTM_DELADDR, 0,
+ ifindex, virtual_ip);
+ if (status == SUCCESS)
+ { /* wait until the address is really gone */
+ while (get_vip_refcount(this, virtual_ip) > 0)
+ {
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ }
+ addrs->destroy(addrs);
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return status;
+ }
+ else
+ {
+ addr->refcount--;
+ }
+ DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
+ virtual_ip);
+ addrs->destroy(addrs);
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ }
+ addrs->destroy(addrs);
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
+ return FAILED;
+}
+
+/**
+ * Manages source routes in the routing table.
+ * By setting the appropriate nlmsg_type, the route gets added or removed.
+ */
+static status_t manage_srcroute(private_kernel_netlink_net_t *this, int nlmsg_type,
+ int flags, chunk_t dst_net, u_int8_t prefixlen,
+ host_t *gateway, host_t *src_ip, char *if_name)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct rtmsg *msg;
+ int ifindex;
+ chunk_t chunk;
+
+ /* if route is 0.0.0.0/0, we can't install it, as it would
+ * overwrite the default route. Instead, we add two routes:
+ * 0.0.0.0/1 and 128.0.0.0/1 */
+ if (this->routing_table == 0 && prefixlen == 0)
+ {
+ chunk_t half_net;
+ u_int8_t half_prefixlen;
+ status_t status;
+
+ half_net = chunk_alloca(dst_net.len);
+ memset(half_net.ptr, 0, half_net.len);
+ half_prefixlen = 1;
+
+ status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
+ gateway, src_ip, if_name);
+ half_net.ptr[0] |= 0x80;
+ status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
+ gateway, src_ip, if_name);
+ return status;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
+ hdr->nlmsg_type = nlmsg_type;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+ msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg->rtm_family = src_ip->get_family(src_ip);
+ msg->rtm_dst_len = prefixlen;
+ msg->rtm_table = this->routing_table;
+ msg->rtm_protocol = RTPROT_STATIC;
+ msg->rtm_type = RTN_UNICAST;
+ msg->rtm_scope = RT_SCOPE_UNIVERSE;
+
+ netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
+ chunk = src_ip->get_address(src_ip);
+ netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
+ if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
+ {
+ chunk = gateway->get_address(gateway);
+ netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
+ }
+ ifindex = get_interface_index(this, if_name);
+ chunk.ptr = (char*)&ifindex;
+ chunk.len = sizeof(ifindex);
+ netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
+
+ return this->socket->send_ack(this->socket, hdr);
+}
+
+/**
+ * Implementation of kernel_net_t.add_route.
+ */
+static status_t add_route(private_kernel_netlink_net_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ return manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
+ dst_net, prefixlen, gateway, src_ip, if_name);
+}
+
+/**
+ * Implementation of kernel_net_t.del_route.
+ */
+static status_t del_route(private_kernel_netlink_net_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ return manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
+ gateway, src_ip, if_name);
+}
+
+/**
+ * Initialize a list of local addresses.
+ */
+static status_t init_address_list(private_kernel_netlink_net_t *this)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *out, *current, *in;
+ struct rtgenmsg *msg;
+ size_t len;
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+
+ DBG1(DBG_KNL, "listening on interfaces:");
+
+ memset(&request, 0, sizeof(request));
+
+ in = (struct nlmsghdr*)&request;
+ in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+ in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
+ msg = (struct rtgenmsg*)NLMSG_DATA(in);
+ msg->rtgen_family = AF_UNSPEC;
+
+ /* get all links */
+ in->nlmsg_type = RTM_GETLINK;
+ if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
+ {
+ return FAILED;
+ }
+ current = out;
+ while (NLMSG_OK(current, len))
+ {
+ switch (current->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ break;
+ case RTM_NEWLINK:
+ process_link(this, current, FALSE);
+ /* fall through */
+ default:
+ current = NLMSG_NEXT(current, len);
+ continue;
+ }
+ break;
+ }
+ free(out);
+
+ /* get all interface addresses */
+ in->nlmsg_type = RTM_GETADDR;
+ if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
+ {
+ return FAILED;
+ }
+ current = out;
+ while (NLMSG_OK(current, len))
+ {
+ switch (current->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ break;
+ case RTM_NEWADDR:
+ process_addr(this, current, FALSE);
+ /* fall through */
+ default:
+ current = NLMSG_NEXT(current, len);
+ continue;
+ }
+ break;
+ }
+ free(out);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->flags & IFF_UP)
+ {
+ DBG1(DBG_KNL, " %s", iface->ifname);
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, (void**)&addr))
+ {
+ DBG1(DBG_KNL, " %H", addr->ip);
+ }
+ addrs->destroy(addrs);
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+}
+
+/**
+ * create or delete a rule to use our routing table
+ */
+static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
+ int family, u_int32_t table, u_int32_t prio)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct rtmsg *msg;
+ chunk_t chunk;
+
+ memset(&request, 0, sizeof(request));
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = nlmsg_type;
+ if (nlmsg_type == RTM_NEWRULE)
+ {
+ hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+ }
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+ msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg->rtm_table = table;
+ msg->rtm_family = family;
+ msg->rtm_protocol = RTPROT_BOOT;
+ msg->rtm_scope = RT_SCOPE_UNIVERSE;
+ msg->rtm_type = RTN_UNICAST;
+
+ chunk = chunk_from_thing(prio);
+ netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
+
+ return this->socket->send_ack(this->socket, hdr);
+}
+
+/**
+ * Implementation of kernel_netlink_net_t.destroy.
+ */
+static void destroy(private_kernel_netlink_net_t *this)
+{
+ if (this->routing_table)
+ {
+ manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
+ this->routing_table_prio);
+ manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
+ this->routing_table_prio);
+ }
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ if (this->socket_events > 0)
+ {
+ close(this->socket_events);
+ }
+ DESTROY_IF(this->socket);
+ this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
+ this->rt_exclude->destroy(this->rt_exclude);
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_netlink_net_t *kernel_netlink_net_create()
+{
+ private_kernel_netlink_net_t *this = malloc_thing(private_kernel_netlink_net_t);
+ struct sockaddr_nl addr;
+ enumerator_t *enumerator;
+ char *exclude;
+
+ /* public functions */
+ this->public.interface.get_interface = (char*(*)(kernel_net_t*,host_t*))get_interface_name;
+ this->public.interface.create_address_enumerator = (enumerator_t*(*)(kernel_net_t*,bool,bool))create_address_enumerator;
+ this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest, host_t *src))get_source_addr;
+ this->public.interface.get_nexthop = (host_t*(*)(kernel_net_t*, host_t *dest))get_nexthop;
+ this->public.interface.add_ip = (status_t(*)(kernel_net_t*,host_t*,host_t*)) add_ip;
+ this->public.interface.del_ip = (status_t(*)(kernel_net_t*,host_t*)) del_ip;
+ this->public.interface.add_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) add_route;
+ this->public.interface.del_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) del_route;
+ this->public.interface.destroy = (void(*)(kernel_net_t*)) destroy;
+
+ /* private members */
+ this->ifaces = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+ timerclear(&this->last_roam);
+ this->routing_table = lib->settings->get_int(lib->settings,
+ "charon.routing_table", ROUTING_TABLE);
+ this->routing_table_prio = lib->settings->get_int(lib->settings,
+ "charon.routing_table_prio", ROUTING_TABLE_PRIO);
+ this->process_route = lib->settings->get_bool(lib->settings,
+ "charon.process_route", TRUE);
+ this->install_virtual_ip = lib->settings->get_bool(lib->settings,
+ "charon.install_virtual_ip", TRUE);
+
+ this->rt_exclude = linked_list_create();
+ exclude = lib->settings->get_str(lib->settings,
+ "charon.ignore_routing_tables", NULL);
+ if (exclude)
+ {
+ char *token;
+ uintptr_t table;
+
+ enumerator = enumerator_create_token(exclude, " ", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ errno = 0;
+ table = strtoul(token, NULL, 10);
+
+ if (errno == 0)
+ {
+ this->rt_exclude->insert_last(this->rt_exclude, (void*)table);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ this->socket = netlink_socket_create(NETLINK_ROUTE);
+ this->job = NULL;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+
+ /* create and bind RT socket for events (address/interface/route changes) */
+ this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (this->socket_events < 0)
+ {
+ DBG1(DBG_KNL, "unable to create RT event socket");
+ destroy(this);
+ return NULL;
+ }
+ addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
+ RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_LINK;
+ if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ DBG1(DBG_KNL, "unable to bind RT event socket");
+ destroy(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ if (init_address_list(this) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to get interface list");
+ destroy(this);
+ return NULL;
+ }
+
+ if (this->routing_table)
+ {
+ if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table,
+ this->routing_table_prio) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to create IPv4 routing table rule");
+ }
+ if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table,
+ this->routing_table_prio) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to create IPv6 routing table rule");
+ }
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h
new file mode 100644
index 000000000..ff9831d3c
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_netlink_net_i kernel_netlink_net
+ * @{ @ingroup kernel_netlink
+ */
+
+#ifndef KERNEL_NETLINK_NET_H_
+#define KERNEL_NETLINK_NET_H_
+
+#include <kernel/kernel_net.h>
+
+typedef struct kernel_netlink_net_t kernel_netlink_net_t;
+
+/**
+ * Implementation of the kernel network interface using Netlink.
+ */
+struct kernel_netlink_net_t {
+
+ /**
+ * Implements kernel_net_t interface
+ */
+ kernel_net_t interface;
+};
+
+/**
+ * Create a netlink kernel network interface instance.
+ *
+ * @return kernel_netlink_net_t instance
+ */
+kernel_netlink_net_t *kernel_netlink_net_create();
+
+#endif /** KERNEL_NETLINK_NET_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
new file mode 100644
index 000000000..4c61265aa
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "kernel_netlink_plugin.h"
+
+#include "kernel_netlink_ipsec.h"
+#include "kernel_netlink_net.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_netlink_plugin_t private_kernel_netlink_plugin_t;
+
+/**
+ * private data of kernel netlink plugin
+ */
+struct private_kernel_netlink_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_netlink_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_netlink_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create);
+ charon->kernel_interface->remove_net_interface(charon->kernel_interface, (kernel_net_constructor_t)kernel_netlink_net_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_netlink_plugin_create()
+{
+ private_kernel_netlink_plugin_t *this = malloc_thing(private_kernel_netlink_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create);
+ charon->kernel_interface->add_net_interface(charon->kernel_interface, (kernel_net_constructor_t)kernel_netlink_net_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h
new file mode 100644
index 000000000..74c9ae24f
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_netlink kernel_netlink
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_netlink_plugin kernel_netlink_plugin
+ * @{ @ingroup kernel_netlink
+ */
+
+#ifndef KERNEL_NETLINK_PLUGIN_H_
+#define KERNEL_NETLINK_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_netlink_plugin_t kernel_netlink_plugin_t;
+
+/**
+ * netlink kernel interface plugin
+ */
+struct kernel_netlink_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_NETLINK_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
new file mode 100644
index 000000000..5ed568150
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -0,0 +1,306 @@
+/*
+ * 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/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "kernel_netlink_shared.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_netlink_socket_t private_netlink_socket_t;
+
+/**
+ * Private variables and functions of netlink_socket_t class.
+ */
+struct private_netlink_socket_t {
+ /**
+ * public part of the netlink_socket_t object.
+ */
+ netlink_socket_t public;
+
+ /**
+ * mutex to lock access to netlink socket
+ */
+ mutex_t *mutex;
+
+ /**
+ * current sequence number for netlink request
+ */
+ int seq;
+
+ /**
+ * netlink socket protocol
+ */
+ int protocol;
+
+ /**
+ * netlink socket
+ */
+ int socket;
+};
+
+/**
+ * Imported from kernel_netlink_ipsec.c
+ */
+extern enum_name_t *xfrm_msg_names;
+
+/**
+ * Implementation of netlink_socket_t.send
+ */
+static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in,
+ struct nlmsghdr **out, size_t *out_len)
+{
+ int len, addr_len;
+ struct sockaddr_nl addr;
+ chunk_t result = chunk_empty, tmp;
+ struct nlmsghdr *msg, peek;
+
+ this->mutex->lock(this->mutex);
+
+ in->nlmsg_seq = ++this->seq;
+ in->nlmsg_pid = getpid();
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = 0;
+ addr.nl_groups = 0;
+
+ if (this->protocol == NETLINK_XFRM)
+ {
+ chunk_t in_chunk = { (u_char*)in, in->nlmsg_len };
+
+ DBG3(DBG_KNL, "sending %N: %B", xfrm_msg_names, in->nlmsg_type, &in_chunk);
+ }
+
+ while (TRUE)
+ {
+ len = sendto(this->socket, in, in->nlmsg_len, 0,
+ (struct sockaddr*)&addr, sizeof(addr));
+
+ if (len != in->nlmsg_len)
+ {
+ if (errno == EINTR)
+ {
+ /* interrupted, try again */
+ continue;
+ }
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "error sending to netlink socket: %s", strerror(errno));
+ return FAILED;
+ }
+ break;
+ }
+
+ while (TRUE)
+ {
+ char buf[4096];
+ tmp.len = sizeof(buf);
+ tmp.ptr = buf;
+ msg = (struct nlmsghdr*)tmp.ptr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = getpid();
+ addr.nl_groups = 0;
+ addr_len = sizeof(addr);
+
+ len = recvfrom(this->socket, tmp.ptr, tmp.len, 0,
+ (struct sockaddr*)&addr, &addr_len);
+
+ if (len < 0)
+ {
+ if (errno == EINTR)
+ {
+ DBG1(DBG_KNL, "got interrupted");
+ /* interrupted, try again */
+ continue;
+ }
+ DBG1(DBG_KNL, "error reading from netlink socket: %s", strerror(errno));
+ this->mutex->unlock(this->mutex);
+ free(result.ptr);
+ return FAILED;
+ }
+ if (!NLMSG_OK(msg, len))
+ {
+ DBG1(DBG_KNL, "received corrupted netlink message");
+ this->mutex->unlock(this->mutex);
+ free(result.ptr);
+ return FAILED;
+ }
+ if (msg->nlmsg_seq != this->seq)
+ {
+ DBG1(DBG_KNL, "received invalid netlink sequence number");
+ if (msg->nlmsg_seq < this->seq)
+ {
+ continue;
+ }
+ this->mutex->unlock(this->mutex);
+ free(result.ptr);
+ return FAILED;
+ }
+
+ tmp.len = len;
+ result.ptr = realloc(result.ptr, result.len + tmp.len);
+ memcpy(result.ptr + result.len, tmp.ptr, tmp.len);
+ result.len += tmp.len;
+
+ /* NLM_F_MULTI flag does not seem to be set correctly, we use sequence
+ * numbers to detect multi header messages */
+ len = recvfrom(this->socket, &peek, sizeof(peek), MSG_PEEK | MSG_DONTWAIT,
+ (struct sockaddr*)&addr, &addr_len);
+
+ if (len == sizeof(peek) && peek.nlmsg_seq == this->seq)
+ {
+ /* seems to be multipart */
+ continue;
+ }
+ break;
+ }
+
+ *out_len = result.len;
+ *out = (struct nlmsghdr*)result.ptr;
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of netlink_socket_t.send_ack.
+ */
+static status_t netlink_send_ack(private_netlink_socket_t *this, struct nlmsghdr *in)
+{
+ struct nlmsghdr *out, *hdr;
+ size_t len;
+
+ if (netlink_send(this, in, &out, &len) != SUCCESS)
+ {
+ return FAILED;
+ }
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr* err = (struct nlmsgerr*)NLMSG_DATA(hdr);
+
+ if (err->error)
+ {
+ if (-err->error == EEXIST)
+ { /* do not report existing routes */
+ free(out);
+ return ALREADY_DONE;
+ }
+ DBG1(DBG_KNL, "received netlink error: %s (%d)",
+ strerror(-err->error), -err->error);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ DBG1(DBG_KNL, "netlink request not acknowledged");
+ free(out);
+ return FAILED;
+}
+
+/**
+ * Implementation of netlink_socket_t.destroy.
+ */
+static void destroy(private_netlink_socket_t *this)
+{
+ if (this->socket > 0)
+ {
+ close(this->socket);
+ }
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+netlink_socket_t *netlink_socket_create(int protocol)
+{
+ private_netlink_socket_t *this = malloc_thing(private_netlink_socket_t);
+ struct sockaddr_nl addr;
+
+ /* public functions */
+ this->public.send = (status_t(*)(netlink_socket_t*,struct nlmsghdr*, struct nlmsghdr**, size_t*))netlink_send;
+ this->public.send_ack = (status_t(*)(netlink_socket_t*,struct nlmsghdr*))netlink_send_ack;
+ this->public.destroy = (void(*)(netlink_socket_t*))destroy;
+
+ /* private members */
+ this->seq = 200;
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+
+ this->protocol = protocol;
+ this->socket = socket(AF_NETLINK, SOCK_RAW, protocol);
+ if (this->socket < 0)
+ {
+ DBG1(DBG_KNL, "unable to create netlink socket");
+ destroy(this);
+ return NULL;
+ }
+
+ addr.nl_groups = 0;
+ if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ DBG1(DBG_KNL, "unable to bind netlink socket");
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
+/**
+ * Described in header.
+ */
+void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
+ size_t buflen)
+{
+ struct rtattr *rta;
+
+ if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(data.len) > buflen)
+ {
+ DBG1(DBG_KNL, "unable to add attribute, buffer too small");
+ return;
+ }
+
+ rta = (struct rtattr*)(((char*)hdr) + NLMSG_ALIGN(hdr->nlmsg_len));
+ rta->rta_type = rta_type;
+ rta->rta_len = RTA_LENGTH(data.len);
+ memcpy(RTA_DATA(rta), data.ptr, data.len);
+ hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len;
+}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h
new file mode 100644
index 000000000..dfd27a21a
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef KERNEL_NETLINK_SHARED_H_
+#define KERNEL_NETLINK_SHARED_H_
+
+#include <library.h>
+
+#include <linux/rtnetlink.h>
+
+/**
+ * General purpose netlink buffer.
+ *
+ * 1024 byte is currently sufficient for all operations. Some platform
+ * require an enforced aligment to four bytes (e.g. ARM).
+ */
+typedef u_char netlink_buf_t[1024] __attribute__((aligned(RTA_ALIGNTO)));
+
+typedef struct netlink_socket_t netlink_socket_t;
+
+/**
+ * Wrapper around a netlink socket.
+ */
+struct netlink_socket_t {
+
+ /**
+ * Send a netlink message and wait for a reply.
+ *
+ * @param in netlink message to send
+ * @param out received netlink message
+ * @param out_len length of the received message
+ */
+ status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out, size_t *out_len);
+
+ /**
+ * Send a netlink message and wait for its acknowledge.
+ *
+ * @param in netlink message to send
+ */
+ status_t (*send_ack)(netlink_socket_t *this, struct nlmsghdr *in);
+
+ /**
+ * Destroy the socket.
+ */
+ void (*destroy)(netlink_socket_t *this);
+};
+
+/**
+ * Create a netlink_socket_t object.
+ *
+ * @param protocol protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE)
+ */
+netlink_socket_t *netlink_socket_create(int protocol);
+
+/**
+ * Creates an rtattr and adds it to the given netlink message.
+ *
+ * @param hdr netlink message
+ * @param rta_type type of the rtattr
+ * @param data data to add to the rtattr
+ * @param buflen length of the netlink message buffer
+ */
+void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, size_t buflen);
+
+#endif /* KERNEL_NETLINK_SHARED_H_ */
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.am b/src/libcharon/plugins/kernel_pfkey/Makefile.am
new file mode 100644
index 000000000..778a7f9a9
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+endif
+
+libstrongswan_kernel_pfkey_la_SOURCES = \
+ kernel_pfkey_plugin.h kernel_pfkey_plugin.c \
+ kernel_pfkey_ipsec.h kernel_pfkey_ipsec.c
+
+libstrongswan_kernel_pfkey_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in
new file mode 100644
index 000000000..2b028ba71
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/kernel_pfkey
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_pfkey_la_LIBADD =
+am_libstrongswan_kernel_pfkey_la_OBJECTS = kernel_pfkey_plugin.lo \
+ kernel_pfkey_ipsec.lo
+libstrongswan_kernel_pfkey_la_OBJECTS = \
+ $(am_libstrongswan_kernel_pfkey_la_OBJECTS)
+libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_pfkey_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfkey_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfkey_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+libstrongswan_kernel_pfkey_la_SOURCES = \
+ kernel_pfkey_plugin.h kernel_pfkey_plugin.c \
+ kernel_pfkey_ipsec.h kernel_pfkey_ipsec.c
+
+libstrongswan_kernel_pfkey_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfkey/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfkey/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-pfkey.la: $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_DEPENDENCIES)
+ $(libstrongswan_kernel_pfkey_la_LINK) $(am_libstrongswan_kernel_pfkey_la_rpath) $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfkey_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfkey_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
new file mode 100644
index 000000000..8a7883c8a
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -0,0 +1,2175 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __FreeBSD__
+#include <limits.h> /* for LONG_MAX */
+#endif
+
+#ifdef HAVE_NET_PFKEYV2_H
+#include <net/pfkeyv2.h>
+#else
+#include <stdint.h>
+#include <linux/pfkeyv2.h>
+#endif
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+#define HAVE_NATT
+#endif
+
+#ifdef HAVE_NETIPSEC_IPSEC_H
+#include <netipsec/ipsec.h>
+#elif defined(HAVE_NETINET6_IPSEC_H)
+#include <netinet6/ipsec.h>
+#else
+#include <linux/ipsec.h>
+#endif
+
+#ifdef HAVE_NATT
+#ifdef HAVE_LINUX_UDP_H
+#include <linux/udp.h>
+#else
+#include <netinet/udp.h>
+#endif /*HAVE_LINUX_UDP_H*/
+#endif /*HAVE_NATT*/
+
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+#include "kernel_pfkey_ipsec.h"
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/migrate_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
+
+/** non linux specific */
+#ifndef IPPROTO_COMP
+#define IPPROTO_COMP IPPROTO_IPCOMP
+#endif
+
+#ifndef SADB_X_AALG_SHA2_256HMAC
+#define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256
+#define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384
+#define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512
+#endif
+
+#ifndef SADB_X_EALG_AESCBC
+#define SADB_X_EALG_AESCBC SADB_X_EALG_AES
+#endif
+
+#ifndef SADB_X_EALG_CASTCBC
+#define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+/** from linux/in.h */
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16
+#endif
+
+/** missing on uclibc */
+#ifndef IPV6_IPSEC_POLICY
+#define IPV6_IPSEC_POLICY 34
+#endif
+
+/** default priority of installed policies */
+#define PRIO_LOW 3000
+#define PRIO_HIGH 2000
+
+#ifdef __APPLE__
+/** from xnu/bsd/net/pfkeyv2.h */
+#define SADB_X_EXT_NATT 0x002
+ struct sadb_sa_2 {
+ struct sadb_sa sa;
+ u_int16_t sadb_sa_natt_port;
+ u_int16_t sadb_reserved0;
+ u_int32_t sadb_reserved1;
+ };
+#endif
+
+/** buffer size for PF_KEY messages */
+#define PFKEY_BUFFER_SIZE 4096
+
+/** PF_KEY messages are 64 bit aligned */
+#define PFKEY_ALIGNMENT 8
+/** aligns len to 64 bits */
+#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1))
+/** calculates the properly padded length in 64 bit chunks */
+#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT))
+/** calculates user mode length i.e. in bytes */
+#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT)
+
+/** given a PF_KEY message header and an extension this updates the length in the header */
+#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len)
+/** given a PF_KEY message header this returns a pointer to the next extension */
+#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len)))
+/** copy an extension and append it to a PF_KEY message */
+#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))))
+/** given a PF_KEY extension this returns a pointer to the next extension */
+#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))
+/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */
+#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext))
+/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */
+#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len <= (len))
+
+typedef struct private_kernel_pfkey_ipsec_t private_kernel_pfkey_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_pfkey class.
+ */
+struct private_kernel_pfkey_ipsec_t
+{
+ /**
+ * Public part of the kernel_pfkey_t object.
+ */
+ kernel_pfkey_ipsec_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * List of installed policies (policy_entry_t)
+ */
+ linked_list_t *policies;
+
+ /**
+ * whether to install routes along policies
+ */
+ bool install_routes;
+
+ /**
+ * job receiving PF_KEY events
+ */
+ callback_job_t *job;
+
+ /**
+ * mutex to lock access to the PF_KEY socket
+ */
+ mutex_t *mutex_pfkey;
+
+ /**
+ * PF_KEY socket to communicate with the kernel
+ */
+ int socket;
+
+ /**
+ * PF_KEY socket to receive acquire and expire events
+ */
+ int socket_events;
+
+ /**
+ * sequence number for messages sent to the kernel
+ */
+ int seq;
+};
+
+typedef struct route_entry_t route_entry_t;
+
+/**
+ * installed routing entry
+ */
+struct route_entry_t {
+ /** Name of the interface the route is bound to */
+ char *if_name;
+
+ /** Source ip of the route */
+ host_t *src_ip;
+
+ /** gateway for this route */
+ host_t *gateway;
+
+ /** Destination net */
+ chunk_t dst_net;
+
+ /** Destination net prefixlen */
+ u_int8_t prefixlen;
+};
+
+/**
+ * destroy an route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+ free(this->if_name);
+ DESTROY_IF(this->src_ip);
+ DESTROY_IF(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+
+ /** reqid of this policy */
+ u_int32_t reqid;
+
+ /** index assigned by the kernel */
+ u_int32_t index;
+
+ /** direction of this policy: in, out, forward */
+ u_int8_t direction;
+
+ /** parameters of installed policy */
+ struct {
+ /** subnet and port */
+ host_t *net;
+ /** subnet mask */
+ u_int8_t mask;
+ /** protocol */
+ u_int8_t proto;
+ } src, dst;
+
+ /** associated route installed for this policy */
+ route_entry_t *route;
+
+ /** by how many CHILD_SA's this policy is used */
+ u_int refcount;
+};
+
+/**
+ * create a policy_entry_t object
+ */
+static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t dir, u_int32_t reqid)
+{
+ policy_entry_t *policy = malloc_thing(policy_entry_t);
+ policy->reqid = reqid;
+ policy->index = 0;
+ policy->direction = dir;
+ policy->route = NULL;
+ policy->refcount = 0;
+
+ src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
+ dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
+
+ /* src or dest proto may be "any" (0), use more restrictive one */
+ policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+ policy->src.proto = policy->src.proto ? policy->src.proto : IPSEC_PROTO_ANY;
+ policy->dst.proto = policy->src.proto;
+
+ return policy;
+}
+
+/**
+ * destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(policy_entry_t *this)
+{
+ DESTROY_IF(this->src.net);
+ DESTROY_IF(this->dst.net);
+ if (this->route)
+ {
+ route_entry_destroy(this->route);
+ }
+ free(this);
+}
+
+/**
+ * compares two policy_entry_t
+ */
+static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy)
+{
+ return current->direction == policy->direction &&
+ current->src.proto == policy->src.proto &&
+ current->dst.proto == policy->dst.proto &&
+ current->src.mask == policy->src.mask &&
+ current->dst.mask == policy->dst.mask &&
+ current->src.net->equals(current->src.net, policy->src.net) &&
+ current->dst.net->equals(current->dst.net, policy->dst.net);
+}
+
+/**
+ * compare the given kernel index with that of a policy
+ */
+static inline bool policy_entry_match_byindex(policy_entry_t *current, u_int32_t *index)
+{
+ return current->index == *index;
+}
+
+typedef struct pfkey_msg_t pfkey_msg_t;
+
+struct pfkey_msg_t
+{
+ /**
+ * PF_KEY message base
+ */
+ struct sadb_msg *msg;
+
+ /**
+ * PF_KEY message extensions
+ */
+ union {
+ struct sadb_ext *ext[SADB_EXT_MAX + 1];
+ struct {
+ struct sadb_ext *reserved; /* SADB_EXT_RESERVED */
+ struct sadb_sa *sa; /* SADB_EXT_SA */
+ struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */
+ struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */
+ struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */
+ struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */
+ struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */
+ struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */
+ struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */
+ struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */
+ struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */
+ struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */
+ struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */
+ struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */
+ struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */
+ struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */
+ struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */
+ struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */
+ struct sadb_x_policy *x_policy; /* SADB_X_EXT_POLICY */
+ struct sadb_x_sa2 *x_sa2; /* SADB_X_EXT_SA2 */
+ struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */
+ struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */
+ struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */
+ struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */
+ struct sadb_x_sec_ctx *x_sec_ctx; /* SADB_X_EXT_SEC_CTX */
+ struct sadb_x_kmaddress *x_kmaddress; /* SADB_X_EXT_KMADDRESS */
+ } __attribute__((__packed__));
+ };
+};
+
+ENUM(sadb_ext_type_names, SADB_EXT_RESERVED, SADB_EXT_MAX,
+ "SADB_EXT_RESERVED",
+ "SADB_EXT_SA",
+ "SADB_EXT_LIFETIME_CURRENT",
+ "SADB_EXT_LIFETIME_HARD",
+ "SADB_EXT_LIFETIME_SOFT",
+ "SADB_EXT_ADDRESS_SRC",
+ "SADB_EXT_ADDRESS_DST",
+ "SADB_EXT_ADDRESS_PROXY",
+ "SADB_EXT_KEY_AUTH",
+ "SADB_EXT_KEY_ENCRYPT",
+ "SADB_EXT_IDENTITY_SRC",
+ "SADB_EXT_IDENTITY_DST",
+ "SADB_EXT_SENSITIVITY",
+ "SADB_EXT_PROPOSAL",
+ "SADB_EXT_SUPPORTED_AUTH",
+ "SADB_EXT_SUPPORTED_ENCRYPT",
+ "SADB_EXT_SPIRANGE",
+ "SADB_X_EXT_KMPRIVATE",
+ "SADB_X_EXT_POLICY",
+ "SADB_X_EXT_SA2",
+ "SADB_X_EXT_NAT_T_TYPE",
+ "SADB_X_EXT_NAT_T_SPORT",
+ "SADB_X_EXT_NAT_T_DPORT",
+ "SADB_X_EXT_NAT_T_OA",
+ "SADB_X_EXT_SEC_CTX",
+ "SADB_X_EXT_KMADDRESS"
+);
+
+/**
+ * convert a IKEv2 specific protocol identifier to the PF_KEY sa type
+ */
+static u_int8_t proto_ike2satype(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return SADB_SATYPE_ESP;
+ case PROTO_AH:
+ return SADB_SATYPE_AH;
+ case IPPROTO_COMP:
+ return SADB_X_SATYPE_IPCOMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a PF_KEY sa type to a IKEv2 specific protocol identifier
+ */
+static protocol_id_t proto_satype2ike(u_int8_t proto)
+{
+ switch (proto)
+ {
+ case SADB_SATYPE_ESP:
+ return PROTO_ESP;
+ case SADB_SATYPE_AH:
+ return PROTO_AH;
+ case SADB_X_SATYPE_IPCOMP:
+ return IPPROTO_COMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a IKEv2 specific protocol identifier to the IP protocol identifier
+ */
+static u_int8_t proto_ike2ip(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return IPPROTO_ESP;
+ case PROTO_AH:
+ return IPPROTO_AH;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert the general ipsec mode to the one defined in ipsec.h
+ */
+static u_int8_t mode2kernel(ipsec_mode_t mode)
+{
+ switch (mode)
+ {
+ case MODE_TRANSPORT:
+ return IPSEC_MODE_TRANSPORT;
+ case MODE_TUNNEL:
+ return IPSEC_MODE_TUNNEL;
+#ifdef HAVE_IPSEC_MODE_BEET
+ case MODE_BEET:
+ return IPSEC_MODE_BEET;
+#endif
+ default:
+ return mode;
+ }
+}
+
+/**
+ * convert the general policy direction to the one defined in ipsec.h
+ */
+static u_int8_t dir2kernel(policy_dir_t dir)
+{
+ switch (dir)
+ {
+ case POLICY_IN:
+ return IPSEC_DIR_INBOUND;
+ case POLICY_OUT:
+ return IPSEC_DIR_OUTBOUND;
+#ifdef HAVE_IPSEC_DIR_FWD
+ case POLICY_FWD:
+ return IPSEC_DIR_FWD;
+#endif
+ default:
+ return IPSEC_DIR_INVALID;
+ }
+}
+
+#ifdef SADB_X_MIGRATE
+/**
+ * convert the policy direction in ipsec.h to the general one.
+ */
+static policy_dir_t kernel2dir(u_int8_t dir)
+{
+ switch (dir)
+ {
+ case IPSEC_DIR_INBOUND:
+ return POLICY_IN;
+ case IPSEC_DIR_OUTBOUND:
+ return POLICY_OUT;
+#ifdef HAVE_IPSEC_DIR_FWD
+ case IPSEC_DIR_FWD:
+ return POLICY_FWD;
+#endif
+ default:
+ return dir;
+ }
+}
+#endif /*SADB_X_MIGRATE*/
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 algorithms to PF_KEY algorithms
+ */
+struct kernel_algorithm_t {
+ /**
+ * Identifier specified in IKEv2
+ */
+ int ikev2;
+
+ /**
+ * Identifier as defined in pfkeyv2.h
+ */
+ int kernel;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/* {ENCR_DES_IV64, 0 }, */
+ {ENCR_DES, SADB_EALG_DESCBC },
+ {ENCR_3DES, SADB_EALG_3DESCBC },
+/* {ENCR_RC5, 0 }, */
+/* {ENCR_IDEA, 0 }, */
+ {ENCR_CAST, SADB_X_EALG_CASTCBC },
+ {ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC },
+/* {ENCR_3IDEA, 0 }, */
+/* {ENCR_DES_IV32, 0 }, */
+ {ENCR_NULL, SADB_EALG_NULL },
+ {ENCR_AES_CBC, SADB_X_EALG_AESCBC },
+/* {ENCR_AES_CTR, SADB_X_EALG_AESCTR }, */
+/* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */
+/* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */
+/* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */
+/* {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 }, */
+/* {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 }, */
+/* {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 }, */
+ {END_OF_LIST, 0 },
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+ {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC },
+ {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC },
+ {AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC },
+ {AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC },
+ {AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC },
+/* {AUTH_DES_MAC, 0, }, */
+/* {AUTH_KPDK_MD5, 0, }, */
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+ {AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, },
+#endif
+ {END_OF_LIST, 0, },
+};
+
+#if 0
+/**
+ * Algorithms for IPComp, unused yet
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, 0 }, */
+ {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE },
+ {IPCOMP_LZS, SADB_X_CALG_LZS },
+ {IPCOMP_LZJH, SADB_X_CALG_LZJH },
+ {END_OF_LIST, 0 },
+};
+#endif
+
+/**
+ * Look up a kernel algorithm ID and its key size
+ */
+static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+{
+ while (list->ikev2 != END_OF_LIST)
+ {
+ if (ikev2 == list->ikev2)
+ {
+ return list->kernel;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * add a host behind a sadb_address extension
+ */
+static void host2ext(host_t *host, struct sadb_address *ext)
+{
+ sockaddr_t *host_addr = host->get_sockaddr(host);
+ socklen_t *len = host->get_sockaddr_len(host);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ host_addr->sa_len = *len;
+#endif
+ 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,
+ u_int8_t proto, u_int8_t prefixlen)
+{
+ struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = type;
+ addr->sadb_address_proto = proto;
+ addr->sadb_address_prefixlen = prefixlen;
+ 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;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ saddr->sa_len = len;
+#endif
+ addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
+ PFKEY_EXT_ADD(msg, addr);
+}
+
+#ifdef HAVE_NATT
+/**
+ * add udp encap extensions to a sadb_msg
+ */
+static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst)
+{
+ struct sadb_x_nat_t_type* nat_type;
+ struct sadb_x_nat_t_port* nat_port;
+
+ nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_type));
+ nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
+ PFKEY_EXT_ADD(msg, nat_type);
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = htons(src->get_port(src));
+ PFKEY_EXT_ADD(msg, nat_port);
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst));
+ PFKEY_EXT_ADD(msg, nat_port);
+}
+#endif /*HAVE_NATT*/
+
+/**
+ * Convert a sadb_address to a traffic_selector
+ */
+static traffic_selector_t* sadb_address2ts(struct sadb_address *address)
+{
+ traffic_selector_t *ts;
+ host_t *host;
+
+ /* The Linux 2.6 kernel does not set the protocol and port information
+ * in the src and dst sadb_address extensions of the SADB_ACQUIRE message.
+ */
+ host = host_create_from_sockaddr((sockaddr_t*)&address[1]) ;
+ ts = traffic_selector_create_from_subnet(host, address->sadb_address_prefixlen,
+ address->sadb_address_proto, host->get_port(host));
+ return ts;
+}
+
+/**
+ * Parses a pfkey message received from the kernel
+ */
+static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out)
+{
+ struct sadb_ext* ext;
+ size_t len;
+
+ memset(out, 0, sizeof(pfkey_msg_t));
+ out->msg = msg;
+
+ len = msg->sadb_msg_len;
+ len -= PFKEY_LEN(sizeof(struct sadb_msg));
+
+ ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg));
+
+ while (len >= PFKEY_LEN(sizeof(struct sadb_ext)))
+ {
+ DBG3(DBG_KNL, " %N", sadb_ext_type_names, ext->sadb_ext_type);
+ if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) ||
+ ext->sadb_ext_len > len)
+ {
+ DBG1(DBG_KNL, "length of %N extension is invalid",
+ sadb_ext_type_names, ext->sadb_ext_type);
+ break;
+ }
+
+ if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type))
+ {
+ DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
+ break;
+ }
+
+ if (out->ext[ext->sadb_ext_type])
+ {
+ DBG1(DBG_KNL, "duplicate %N extension",
+ sadb_ext_type_names, ext->sadb_ext_type);
+ break;
+ }
+
+ out->ext[ext->sadb_ext_type] = ext;
+ ext = PFKEY_EXT_NEXT_LEN(ext, len);
+ }
+
+ if (len)
+ {
+ DBG1(DBG_KNL, "PF_KEY message length is invalid");
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to a specific PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send_socket(private_kernel_pfkey_ipsec_t *this, int socket,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg;
+ int in_len, len;
+
+ this->mutex_pfkey->lock(this->mutex_pfkey);
+
+ /* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367,
+ * in particular the behavior in response to an SADB_ACQUIRE. */
+ in->sadb_msg_seq = ++this->seq;
+ in->sadb_msg_pid = getpid();
+
+ in_len = PFKEY_USER_LEN(in->sadb_msg_len);
+
+ while (TRUE)
+ {
+ len = send(socket, in, in_len, 0);
+
+ if (len != in_len)
+ {
+ if (errno == EINTR)
+ {
+ /* interrupted, try again */
+ continue;
+ }
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "error sending to PF_KEY socket: %s", strerror(errno));
+ return FAILED;
+ }
+ break;
+ }
+
+ while (TRUE)
+ {
+ msg = (struct sadb_msg*)buf;
+
+ len = recv(socket, buf, sizeof(buf), 0);
+
+ if (len < 0)
+ {
+ if (errno == EINTR)
+ {
+ DBG1(DBG_KNL, "got interrupted");
+ /* interrupted, try again */
+ continue;
+ }
+ DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", strerror(errno));
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (len < sizeof(struct sadb_msg) ||
+ msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
+ {
+ DBG1(DBG_KNL, "received corrupted PF_KEY message");
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+ {
+ DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_pid != in->sadb_msg_pid)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message is not intended for us");
+ continue;
+ }
+ if (msg->sadb_msg_seq != this->seq)
+ {
+ DBG1(DBG_KNL, "received PF_KEY message with unexpected sequence "
+ "number, was %d expected %d", msg->sadb_msg_seq, this->seq);
+ if (msg->sadb_msg_seq == 0)
+ {
+ /* FreeBSD and Mac OS X do this for the response to
+ * SADB_X_SPDGET (but not for the response to SADB_GET).
+ * FreeBSD: 'key_spdget' in /usr/src/sys/netipsec/key.c. */
+ }
+ else if (msg->sadb_msg_seq < this->seq)
+ {
+ continue;
+ }
+ else
+ {
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ }
+ if (msg->sadb_msg_type != in->sadb_msg_type)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message of wrong type, "
+ "was %d expected %d, ignoring",
+ msg->sadb_msg_type, in->sadb_msg_type);
+ }
+ break;
+ }
+
+ *out_len = len;
+ *out = (struct sadb_msg*)malloc(len);
+ memcpy(*out, buf, len);
+
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to the default PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send(private_kernel_pfkey_ipsec_t *this,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ return pfkey_send_socket(this, this->socket, in, out, out_len);
+}
+
+/**
+ * Process a SADB_ACQUIRE message from the kernel
+ */
+static void process_acquire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t index, reqid = 0;
+ traffic_selector_t *src_ts, *dst_ts;
+ policy_entry_t *policy;
+ job_t *job;
+
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_UNSPEC:
+ case SADB_SATYPE_ESP:
+ case SADB_SATYPE_AH:
+ break;
+ default:
+ /* acquire for AH/ESP only */
+ return;
+ }
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed");
+ return;
+ }
+
+ index = response.x_policy->sadb_x_policy_id;
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_match_byindex, (void**)&policy, &index) == SUCCESS)
+ {
+ reqid = policy->reqid;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no matching policy found",
+ index);
+ }
+ src_ts = sadb_address2ts(response.src);
+ dst_ts = sadb_address2ts(response.dst);
+ this->mutex->unlock(this->mutex);
+
+ DBG1(DBG_KNL, "creating acquire job for policy %R === %R with reqid {%u}",
+ src_ts, dst_ts, reqid);
+ job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts);
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * Process a SADB_EXPIRE message from the kernel
+ */
+static void process_expire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ protocol_id_t protocol;
+ u_int32_t spi, reqid;
+ bool hard;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_EXPIRE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_EXPIRE from kernel failed");
+ return;
+ }
+
+ protocol = proto_satype2ike(msg->sadb_msg_satype);
+ spi = response.sa->sadb_sa_spi;
+ reqid = response.x_sa2->sadb_x_sa2_reqid;
+ hard = response.lft_hard != NULL;
+
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ DBG2(DBG_KNL, "ignoring SADB_EXPIRE for SA with SPI %.8x and reqid {%u} "
+ "which is not a CHILD_SA", ntohl(spi), reqid);
+ return;
+ }
+
+ DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%u}",
+ hard ? "delete" : "rekey", protocol_id_names,
+ protocol, ntohl(spi), reqid);
+ if (hard)
+ {
+ job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
+ }
+ else
+ {
+ job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
+ }
+ charon->processor->queue_job(charon->processor, job);
+}
+
+#ifdef SADB_X_MIGRATE
+/**
+ * Process a SADB_X_MIGRATE message from the kernel
+ */
+static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ traffic_selector_t *src_ts, *dst_ts;
+ policy_dir_t dir;
+ u_int32_t reqid = 0;
+ host_t *local = NULL, *remote = NULL;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_MIGRATE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_MIGRATE from kernel failed");
+ return;
+ }
+ src_ts = sadb_address2ts(response.src);
+ dst_ts = sadb_address2ts(response.dst);
+ dir = kernel2dir(response.x_policy->sadb_x_policy_dir);
+ DBG2(DBG_KNL, " policy %R === %R %N, id %u", src_ts, dst_ts,
+ policy_dir_names, dir);
+
+ /* SADB_X_EXT_KMADDRESS is not present in unpatched kernels < 2.6.28 */
+ if (response.x_kmaddress)
+ {
+ sockaddr_t *local_addr, *remote_addr;
+ u_int32_t local_len;
+
+ local_addr = (sockaddr_t*)&response.x_kmaddress[1];
+ local = host_create_from_sockaddr(local_addr);
+ local_len = (local_addr->sa_family == AF_INET6)?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+ remote_addr = (sockaddr_t*)((u_int8_t*)local_addr + local_len);
+ remote = host_create_from_sockaddr(remote_addr);
+ DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote);
+ }
+
+ if (src_ts && dst_ts && local && remote)
+ {
+ DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
+ src_ts, dst_ts, policy_dir_names, dir, reqid, local);
+ job = (job_t*)migrate_job_create(reqid, src_ts, dst_ts, dir,
+ local, remote);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ else
+ {
+ DESTROY_IF(src_ts);
+ DESTROY_IF(dst_ts);
+ DESTROY_IF(local);
+ DESTROY_IF(remote);
+ }
+}
+#endif /*SADB_X_MIGRATE*/
+
+#ifdef HAVE_NATT
+/**
+ * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
+ */
+static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t spi, reqid;
+ host_t *host;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed");
+ return;
+ }
+
+ if (!response.x_sa2)
+ {
+ DBG1(DBG_KNL, "received SADB_X_NAT_T_NEW_MAPPING is missing required information");
+ return;
+ }
+
+ spi = response.sa->sadb_sa_spi;
+ reqid = response.x_sa2->sadb_x_sa2_reqid;
+
+ if (proto_satype2ike(msg->sadb_msg_satype) == PROTO_ESP)
+ {
+ sockaddr_t *sa = (sockaddr_t*)(response.dst + 1);
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in*)sa;
+ sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
+ sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ default:
+ break;
+ }
+ host = host_create_from_sockaddr(sa);
+ if (host)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and "
+ "reqid {%u} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, host);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+#endif /*HAVE_NATT*/
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)buf;
+ int len;
+ bool oldstate;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->socket_events, buf, sizeof(buf), 0, NULL, 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:
+ process_expire(this, msg);
+ break;
+#ifdef SADB_X_MIGRATE
+ case SADB_X_MIGRATE:
+ process_migrate(this, msg);
+ break;
+#endif /*SADB_X_MIGRATE*/
+#ifdef HAVE_NATT
+ case SADB_X_NAT_T_NEW_MAPPING:
+ process_mapping(this, msg);
+ break;
+#endif /*HAVE_NATT*/
+ default:
+ break;
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+ private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_sa2 *sa2;
+ struct sadb_spirange *range;
+ pfkey_msg_t response;
+ u_int32_t received_spi = 0;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_GETSPI;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ sa2->sadb_x_sa2_reqid = reqid;
+ PFKEY_EXT_ADD(msg, sa2);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+
+ range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg);
+ range->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+ range->sadb_spirange_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ range->sadb_spirange_min = 0xc0000000;
+ range->sadb_spirange_max = 0xcFFFFFFF;
+ PFKEY_EXT_ADD(msg, range);
+
+ if (pfkey_send(this, msg, &out, &len) == SUCCESS)
+ {
+ if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "allocating SPI failed: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ }
+ else if (parse_pfkey_message(out, &response) == SUCCESS)
+ {
+ received_spi = response.sa->sadb_sa_spi;
+ }
+ free(out);
+ }
+
+ if (received_spi == 0)
+ {
+ return FAILED;
+ }
+
+ *spi = received_spi;
+ return SUCCESS;
+}
+
+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;
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+ private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid, 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 encap,
+ 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_x_sa2 *sa2;
+ struct sadb_lifetime *lft;
+ struct sadb_key *key;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = inbound ? SADB_UPDATE : SADB_ADD;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+#ifdef __APPLE__
+ if (encap)
+ {
+ struct sadb_sa_2 *sa_2;
+ sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa_2->sadb_sa_natt_port = dst->get_port(dst);
+ sa = &sa_2->sa;
+ sa->sadb_sa_flags |= SADB_X_EXT_NATT;
+ len = sizeof(struct sadb_sa_2);
+ }
+ else
+#endif
+ {
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ len = sizeof(struct sadb_sa);
+ }
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(len);
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
+ sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ PFKEY_EXT_ADD(msg, sa);
+
+ sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ sa2->sadb_x_sa2_mode = mode2kernel(mode);
+ sa2->sadb_x_sa2_reqid = reqid;
+ PFKEY_EXT_ADD(msg, sa2);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+
+ lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
+ lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
+ lft->sadb_lifetime_allocations = lifetime->packets.rekey;
+ lft->sadb_lifetime_bytes = lifetime->bytes.rekey;
+ lft->sadb_lifetime_addtime = lifetime->time.rekey;
+ lft->sadb_lifetime_usetime = 0; /* we only use addtime */
+ PFKEY_EXT_ADD(msg, lft);
+
+ lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
+ lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
+ lft->sadb_lifetime_allocations = lifetime->packets.life;
+ lft->sadb_lifetime_bytes = lifetime->bytes.life;
+ lft->sadb_lifetime_addtime = lifetime->time.life;
+ lft->sadb_lifetime_usetime = 0; /* we only use addtime */
+ PFKEY_EXT_ADD(msg, lft);
+
+ if (enc_alg != ENCR_UNDEFINED)
+ {
+ if (!sa->sadb_sa_encrypt)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ encryption_algorithm_names, enc_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ key->sadb_key_bits = enc_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
+ memcpy(key + 1, enc_key.ptr, enc_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ if (!sa->sadb_sa_auth)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ integrity_algorithm_names, int_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
+ integrity_algorithm_names, int_alg, int_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ key->sadb_key_bits = int_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
+ memcpy(key + 1, int_key.ptr, int_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ /*TODO*/
+ }
+
+#ifdef HAVE_NATT
+ if (encap)
+ {
+ add_encap_ext(msg, src, dst);
+ }
+#endif /*HAVE_NATT*/
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+ private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ pfkey_msg_t response;
+ size_t len;
+
+ /* we can't update the SA if any of the ip addresses have changed.
+ * that's because we can't use SADB_UPDATE and by deleting and readding the
+ * SA the sequence numbers would get lost */
+ if (!src->ip_equals(src, new_src) ||
+ !dst->ip_equals(dst, new_dst))
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes"
+ " are not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_GET;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
+ * it is not used for anything. */
+ add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+ ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing response "
+ "from kernel failed", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_UPDATE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+#ifdef __APPLE__
+ {
+ struct sadb_sa_2 *sa_2;
+ sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
+ memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
+ if (encap)
+ {
+ sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst);
+ sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
+ }
+ }
+#else
+ PFKEY_EXT_COPY(msg, response.sa);
+#endif
+ PFKEY_EXT_COPY(msg, response.x_sa2);
+
+ PFKEY_EXT_COPY(msg, response.src);
+ PFKEY_EXT_COPY(msg, response.dst);
+
+ PFKEY_EXT_COPY(msg, response.lft_soft);
+ PFKEY_EXT_COPY(msg, response.lft_hard);
+
+ if (response.key_encr)
+ {
+ PFKEY_EXT_COPY(msg, response.key_encr);
+ }
+
+ if (response.key_auth)
+ {
+ PFKEY_EXT_COPY(msg, response.key_auth);
+ }
+
+#ifdef HAVE_NATT
+ if (new_encap)
+ {
+ add_encap_ext(msg, new_src, new_dst);
+ }
+#endif /*HAVE_NATT*/
+
+ free(out);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+ private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ pfkey_msg_t response;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_GET;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the Linux Kernel doesn't care for the src address, but other systems do
+ * (e.g. FreeBSD)
+ */
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+ *bytes = response.lft_current->sadb_lifetime_bytes;
+
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+ private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ 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, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_DELETE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the Linux Kernel doesn't care for the src address, but other systems do
+ * (e.g. FreeBSD)
+ */
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+
+ 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_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ struct sadb_x_ipsecrequest *req;
+ policy_entry_t *policy, *found = NULL;
+ pfkey_msg_t response;
+ size_t len;
+
+ if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+ {
+ /* FWD policies are not supported on all platforms */
+ return SUCCESS;
+ }
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, reqid);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ /* use existing policy */
+ found->refcount++;
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
+ "refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ /* apply the new one, if we have no such policy */
+ this->policies->insert_last(this->policies, policy);
+ policy->refcount = 1;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = found ? SADB_X_SPDUPDATE : SADB_X_SPDADD;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_id = 0;
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+#ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY
+ /* calculate priority based on source selector size, small size = high prio */
+ pol->sadb_x_policy_priority = routed ? PRIO_LOW : PRIO_HIGH;
+ pol->sadb_x_policy_priority -= policy->src.mask * 10;
+ pol->sadb_x_policy_priority -= policy->src.proto != IPSEC_PROTO_ANY ? 2 : 0;
+ pol->sadb_x_policy_priority -= policy->src.net->get_port(policy->src.net) ? 1 : 0;
+#endif
+
+ /* one or more sadb_x_ipsecrequest extensions are added to the sadb_x_policy extension */
+ req = (struct sadb_x_ipsecrequest*)(pol + 1);
+ req->sadb_x_ipsecrequest_proto = proto_ike2ip(protocol);
+ /* !!! the length of this struct MUST be in octets instead of 64 bit words */
+ req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
+ req->sadb_x_ipsecrequest_mode = mode2kernel(mode);
+ req->sadb_x_ipsecrequest_reqid = reqid;
+ req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
+ if (mode == MODE_TUNNEL)
+ {
+ sockaddr_t *sa;
+ socklen_t sl;
+ sa = src->get_sockaddr(src);
+ sl = *src->get_sockaddr_len(src);
+ memcpy(req + 1, sa, sl);
+ sa = dst->get_sockaddr(dst);
+ memcpy((u_int8_t*)(req + 1) + sl, sa, sl);
+ req->sadb_x_ipsecrequest_len += sl * 2;
+ }
+
+ pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
+ PFKEY_EXT_ADD(msg, pol);
+
+ add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+ policy->src.mask);
+ add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+ policy->dst.mask);
+
+#ifdef __FreeBSD__
+ { /* on FreeBSD a lifetime has to be defined to be able to later query
+ * the current use time. */
+ struct sadb_lifetime *lft;
+ lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
+ lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
+ lft->sadb_lifetime_addtime = LONG_MAX;
+ PFKEY_EXT_ADD(msg, lft);
+ }
+#endif
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts,
+ policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: parsing response "
+ "from kernel failed", src_ts, dst_ts, policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+
+ this->mutex->lock(this->mutex);
+
+ /* we try to find the policy again and update the kernel index */
+ if (this->policies->find_last(this->policies, NULL, (void**)&policy) != SUCCESS)
+ {
+ DBG2(DBG_KNL, "unable to update index, the policy %R === %R %N is "
+ "already gone, ignoring", src_ts, dst_ts, policy_dir_names, direction);
+ this->mutex->unlock(this->mutex);
+ free(out);
+ return SUCCESS;
+ }
+ policy->index = response.x_policy->sadb_x_policy_id;
+ free(out);
+
+ /* install a route, if:
+ * - we are NOT updating a policy
+ * - this is a forward policy (to just get one for each child)
+ * - we are in tunnel mode
+ * - we are not using IPv6 (does not work correctly yet!)
+ * - routing is not disabled via strongswan.conf
+ */
+ if (policy->route == NULL && direction == POLICY_FWD &&
+ mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 &&
+ this->install_routes)
+ {
+ route_entry_t *route = malloc_thing(route_entry_t);
+
+ if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ dst_ts, &route->src_ip) == SUCCESS)
+ {
+ /* get the nexthop to src (src as we are in POLICY_FWD).*/
+ route->gateway = charon->kernel_interface->get_nexthop(
+ charon->kernel_interface, src);
+ route->if_name = charon->kernel_interface->get_interface(
+ charon->kernel_interface, dst);
+ route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net));
+ route->prefixlen = policy->src.mask;
+
+ switch (charon->kernel_interface->add_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install source route for %H",
+ route->src_ip);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+ else
+ {
+ free(route);
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+ private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ policy_entry_t *policy, *found = NULL;
+ pfkey_msg_t response;
+ size_t len;
+
+ if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+ {
+ /* FWD policies are not supported on all platforms */
+ return NOT_FOUND;
+ }
+
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, 0);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+ policy = found;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_SPDGET;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_id = policy->index;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+ PFKEY_EXT_ADD(msg, pol);
+
+ add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+ policy->src.mask);
+ add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+ policy->dst.mask);
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response "
+ "from kernel failed", src_ts, dst_ts, policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+ else if (response.lft_current == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
+ "use time", src_ts, dst_ts, policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+ /* we need the monotonic time, but the kernel returns system time. */
+ if (response.lft_current->sadb_lifetime_usetime)
+ {
+ *use_time = time_monotonic(NULL) -
+ (time(NULL) - response.lft_current->sadb_lifetime_usetime);
+ }
+ else
+ {
+ *use_time = 0;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+ private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ policy_entry_t *policy, *found = NULL;
+ route_entry_t *route;
+ size_t len;
+
+ if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+ {
+ /* FWD policies are not supported on all platforms */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, 0);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ if (--found->refcount > 0)
+ {
+ /* is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ /* remove if last reference */
+ this->policies->remove(this->policies, found, NULL);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+ this->mutex->unlock(this->mutex);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_SPDDELETE;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+ PFKEY_EXT_ADD(msg, pol);
+
+ add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+ policy->src.mask);
+ add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+ policy->dst.mask);
+
+ route = policy->route;
+ policy->route = NULL;
+ policy_entry_destroy(policy);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ if (route)
+ {
+ if (charon->kernel_interface->del_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "error uninstalling route installed with "
+ "policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
+ route_entry_destroy(route);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Register a socket for AQUIRE/EXPIRE messages
+ */
+static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this,
+ u_int8_t satype)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_REGISTER;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket");
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_pfkey_ipsec_t *this, int fd, int family)
+{
+ struct sadb_x_policy policy;
+ u_int sol, ipsec_policy;
+
+ switch (family)
+ {
+ case AF_INET:
+ {
+ sol = SOL_IP;
+ ipsec_policy = IP_IPSEC_POLICY;
+ break;
+ }
+ case AF_INET6:
+ {
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_IPSEC_POLICY;
+ break;
+ }
+ default:
+ return FALSE;
+ }
+
+ memset(&policy, 0, sizeof(policy));
+ policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
+ policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
+
+ policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_pfkey_ipsec_t *this)
+{
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ if (this->socket > 0)
+ {
+ close(this->socket);
+ }
+ if (this->socket_events > 0)
+ {
+ close(this->socket_events);
+ }
+ this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
+ this->mutex->destroy(this->mutex);
+ this->mutex_pfkey->destroy(this->mutex_pfkey);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
+{
+ private_kernel_pfkey_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,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
+ .destroy = _destroy,
+ },
+ .policies = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .mutex_pfkey = mutex_create(MUTEX_TYPE_DEFAULT),
+ .install_routes = lib->settings->get_bool(lib->settings,
+ "charon.install_routes", TRUE),
+ );
+
+ /* 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;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
new file mode 100644
index 000000000..649f93733
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_pfkey_ipsec_i kernel_pfkey_ipsec
+ * @{ @ingroup kernel_pfkey
+ */
+
+#ifndef KERNEL_PFKEY_IPSEC_H_
+#define KERNEL_PFKEY_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_pfkey_ipsec_t kernel_pfkey_ipsec_t;
+
+/**
+ * Implementation of the kernel ipsec interface using PF_KEY.
+ */
+struct kernel_pfkey_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a PF_KEY kernel ipsec interface instance.
+ *
+ * @return kernel_pfkey_ipsec_t instance
+ */
+kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create();
+
+#endif /** KERNEL_PFKEY_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
new file mode 100644
index 000000000..b84ccf150
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "kernel_pfkey_plugin.h"
+
+#include "kernel_pfkey_ipsec.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_pfkey_plugin_t private_kernel_pfkey_plugin_t;
+
+/**
+ * private data of kernel PF_KEY plugin
+ */
+struct private_kernel_pfkey_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_pfkey_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_pfkey_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_pfkey_plugin_create()
+{
+ private_kernel_pfkey_plugin_t *this = malloc_thing(private_kernel_pfkey_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
new file mode 100644
index 000000000..ecccc6303
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_pfkey kernel_pfkey
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_pfkey_plugin kernel_pfkey_plugin
+ * @{ @ingroup kernel_pfkey
+ */
+
+#ifndef KERNEL_PFKEY_PLUGIN_H_
+#define KERNEL_PFKEY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_pfkey_plugin_t kernel_pfkey_plugin_t;
+
+/**
+ * PF_KEY kernel interface plugin
+ */
+struct kernel_pfkey_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_PFKEY_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.am b/src/libcharon/plugins/kernel_pfroute/Makefile.am
new file mode 100644
index 000000000..83db48160
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+endif
+
+libstrongswan_kernel_pfroute_la_SOURCES = \
+ kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
+ kernel_pfroute_net.h kernel_pfroute_net.c
+
+libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in
new file mode 100644
index 000000000..3a4d2c3b5
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/kernel_pfroute
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_pfroute_la_LIBADD =
+am_libstrongswan_kernel_pfroute_la_OBJECTS = kernel_pfroute_plugin.lo \
+ kernel_pfroute_net.lo
+libstrongswan_kernel_pfroute_la_OBJECTS = \
+ $(am_libstrongswan_kernel_pfroute_la_OBJECTS)
+libstrongswan_kernel_pfroute_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_pfroute_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfroute_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfroute_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+libstrongswan_kernel_pfroute_la_SOURCES = \
+ kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
+ kernel_pfroute_net.h kernel_pfroute_net.c
+
+libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfroute/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfroute/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-pfroute.la: $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_DEPENDENCIES)
+ $(libstrongswan_kernel_pfroute_la_LINK) $(am_libstrongswan_kernel_pfroute_la_rpath) $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfroute_net.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfroute_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
new file mode 100644
index 000000000..97c019b58
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <net/route.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "kernel_pfroute_net.h"
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/roam_job.h>
+
+#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
+#error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
+#endif
+
+/** delay before firing roam jobs (ms) */
+#define ROAM_DELAY 100
+
+/** buffer size for PF_ROUTE messages */
+#define PFROUTE_BUFFER_SIZE 4096
+
+typedef struct addr_entry_t addr_entry_t;
+
+/**
+ * IP address in an inface_entry_t
+ */
+struct addr_entry_t {
+
+ /** The ip address */
+ host_t *ip;
+
+ /** virtual IP managed by us */
+ bool virtual;
+
+ /** Number of times this IP is used, if virtual */
+ u_int refcount;
+};
+
+/**
+ * destroy a addr_entry_t object
+ */
+static void addr_entry_destroy(addr_entry_t *this)
+{
+ this->ip->destroy(this->ip);
+ free(this);
+}
+
+typedef struct iface_entry_t iface_entry_t;
+
+/**
+ * A network interface on this system, containing addr_entry_t's
+ */
+struct iface_entry_t {
+
+ /** interface index */
+ int ifindex;
+
+ /** name of the interface */
+ char ifname[IFNAMSIZ];
+
+ /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
+ u_int flags;
+
+ /** list of addresses as host_t */
+ linked_list_t *addrs;
+};
+
+/**
+ * destroy an interface entry
+ */
+static void iface_entry_destroy(iface_entry_t *this)
+{
+ this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
+ free(this);
+}
+
+
+typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
+
+/**
+ * Private variables and functions of kernel_pfroute class.
+ */
+struct private_kernel_pfroute_net_t
+{
+ /**
+ * Public part of the kernel_pfroute_t object.
+ */
+ kernel_pfroute_net_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * Cached list of interfaces and their addresses (iface_entry_t)
+ */
+ linked_list_t *ifaces;
+
+ /**
+ * job receiving PF_ROUTE events
+ */
+ callback_job_t *job;
+
+ /**
+ * mutex to lock access to the PF_ROUTE socket
+ */
+ mutex_t *mutex_pfroute;
+
+ /**
+ * PF_ROUTE socket to communicate with the kernel
+ */
+ int socket;
+
+ /**
+ * PF_ROUTE socket to receive events
+ */
+ int socket_events;
+
+ /**
+ * sequence number for messages sent to the kernel
+ */
+ int seq;
+
+ /**
+ * time of last roam job
+ */
+ timeval_t last_roam;
+};
+
+/**
+ * Start a roaming job. We delay it a bit and fire only one job
+ * for multiple events. Otherwise we would create too many jobs.
+ */
+static void fire_roam_job(private_kernel_pfroute_net_t *this, bool address)
+{
+ timeval_t now;
+
+ time_monotonic(&now);
+ if (timercmp(&now, &this->last_roam, >))
+ {
+ now.tv_usec += ROAM_DELAY * 1000;
+ while (now.tv_usec > 1000000)
+ {
+ now.tv_sec++;
+ now.tv_usec -= 1000000;
+ }
+ this->last_roam = now;
+ charon->scheduler->schedule_job_ms(charon->scheduler,
+ (job_t*)roam_job_create(address), ROAM_DELAY);
+ }
+}
+
+/**
+ * Process an RTM_*ADDR message from the kernel
+ */
+static void process_addr(private_kernel_pfroute_net_t *this,
+ struct rt_msghdr *msg)
+{
+ struct ifa_msghdr *ifa = (struct ifa_msghdr*)msg;
+ sockaddr_t *sockaddr = (sockaddr_t*)(ifa + 1);
+ host_t *host = NULL;
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ bool found = FALSE, changed = FALSE, roam = FALSE;
+ int i;
+
+ for (i = 1; i < (1 << RTAX_MAX); i <<= 1)
+ {
+ if (ifa->ifam_addrs & i)
+ {
+ if (RTA_IFA & i)
+ {
+ host = host_create_from_sockaddr(sockaddr);
+ break;
+ }
+ sockaddr = (sockaddr_t*)((char*)sockaddr + sockaddr->sa_len);
+ }
+ }
+
+ if (!host)
+ {
+ return;
+ }
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == ifa->ifam_index)
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (host->ip_equals(host, addr->ip))
+ {
+ found = TRUE;
+ if (ifa->ifam_type == RTM_DELADDR)
+ {
+ iface->addrs->remove_at(iface->addrs, addrs);
+ if (!addr->virtual)
+ {
+ changed = TRUE;
+ DBG1(DBG_KNL, "%H disappeared from %s",
+ host, iface->ifname);
+ }
+ addr_entry_destroy(addr);
+ }
+ else if (ifa->ifam_type == RTM_NEWADDR && addr->virtual)
+ {
+ addr->refcount = 1;
+ }
+ }
+ }
+ addrs->destroy(addrs);
+
+ if (!found && ifa->ifam_type == RTM_NEWADDR)
+ {
+ changed = TRUE;
+ addr = malloc_thing(addr_entry_t);
+ addr->ip = host->clone(host);
+ addr->virtual = FALSE;
+ addr->refcount = 1;
+ iface->addrs->insert_last(iface->addrs, addr);
+ DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+ }
+
+ if (changed && (iface->flags & IFF_UP))
+ {
+ roam = TRUE;
+ }
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ host->destroy(host);
+
+ if (roam)
+ {
+ fire_roam_job(this, TRUE);
+ }
+}
+
+/**
+ * Process an RTM_IFINFO message from the kernel
+ */
+static void process_link(private_kernel_pfroute_net_t *this,
+ struct rt_msghdr *hdr)
+{
+ struct if_msghdr *msg = (struct if_msghdr*)hdr;
+ enumerator_t *enumerator;
+ iface_entry_t *iface;
+ bool roam = FALSE;
+
+ if (msg->ifm_flags & IFF_LOOPBACK)
+ { /* ignore loopback interfaces */
+ return;
+ }
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &iface))
+ {
+ if (iface->ifindex == msg->ifm_index)
+ {
+ if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
+ {
+ roam = TRUE;
+ DBG1(DBG_KNL, "interface %s activated", iface->ifname);
+ }
+ else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
+ {
+ roam = TRUE;
+ DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
+ }
+ iface->flags = msg->ifm_flags;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (roam)
+ {
+ fire_roam_job(this, TRUE);
+ }
+}
+
+/**
+ * Process an RTM_*ROUTE message from the kernel
+ */
+static void process_route(private_kernel_pfroute_net_t *this,
+ struct rt_msghdr *msg)
+{
+
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_pfroute_net_t *this)
+{
+ unsigned char buf[PFROUTE_BUFFER_SIZE];
+ struct rt_msghdr *msg = (struct rt_msghdr*)buf;
+ int len;
+ bool oldstate;
+
+ oldstate = thread_cancelability(TRUE);
+ len = recvfrom(this->socket_events, buf, sizeof(buf), 0, NULL, 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_ROUTE event socket");
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+ }
+
+ if (len < sizeof(msg->rtm_msglen) || len < msg->rtm_msglen ||
+ msg->rtm_version != RTM_VERSION)
+ {
+ DBG2(DBG_KNL, "received corrupted PF_ROUTE message");
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ switch (msg->rtm_type)
+ {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ process_addr(this, msg);
+ break;
+ case RTM_IFINFO:
+ /*case RTM_IFANNOUNCE <- what about this*/
+ process_link(this, msg);
+ break;
+ case RTM_ADD:
+ case RTM_DELETE:
+ process_route(this, msg);
+ default:
+ break;
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+
+/** enumerator over addresses */
+typedef struct {
+ private_kernel_pfroute_net_t* this;
+ /** whether to enumerate down interfaces */
+ bool include_down_ifaces;
+ /** whether to enumerate virtual ip addresses */
+ bool include_virtual_ips;
+} address_enumerator_t;
+
+/**
+ * cleanup function for address enumerator
+ */
+static void address_enumerator_destroy(address_enumerator_t *data)
+{
+ data->this->mutex->unlock(data->this->mutex);
+ free(data);
+}
+
+/**
+ * filter for addresses
+ */
+static bool filter_addresses(address_enumerator_t *data, addr_entry_t** in, host_t** out)
+{
+ host_t *ip;
+ if (!data->include_virtual_ips && (*in)->virtual)
+ { /* skip virtual interfaces added by us */
+ return FALSE;
+ }
+ ip = (*in)->ip;
+ if (ip->get_family(ip) == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ { /* skip addresses with a unusable scope */
+ return FALSE;
+ }
+ }
+ *out = ip;
+ return TRUE;
+}
+
+/**
+ * enumerator constructor for interfaces
+ */
+static enumerator_t *create_iface_enumerator(iface_entry_t *iface, address_enumerator_t *data)
+{
+ return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
+ (void*)filter_addresses, data, NULL);
+}
+
+/**
+ * filter for interfaces
+ */
+static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out)
+{
+ if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
+ { /* skip interfaces not up */
+ return FALSE;
+ }
+ *out = *in;
+ return TRUE;
+}
+
+/**
+ * implementation of kernel_net_t.create_address_enumerator
+ */
+static enumerator_t *create_address_enumerator(private_kernel_pfroute_net_t *this,
+ bool include_down_ifaces, bool include_virtual_ips)
+{
+ address_enumerator_t *data = malloc_thing(address_enumerator_t);
+ data->this = this;
+ data->include_down_ifaces = include_down_ifaces;
+ data->include_virtual_ips = include_virtual_ips;
+
+ this->mutex->lock(this->mutex);
+ return enumerator_create_nested(
+ enumerator_create_filter(this->ifaces->create_enumerator(this->ifaces),
+ (void*)filter_interfaces, data, NULL),
+ (void*)create_iface_enumerator, data, (void*)address_enumerator_destroy);
+}
+
+/**
+ * implementation of kernel_net_t.get_interface_name
+ */
+static char *get_interface_name(private_kernel_pfroute_net_t *this, host_t* ip)
+{
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ char *name = NULL;
+
+ DBG2(DBG_KNL, "getting interface name for %H", ip);
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (ip->ip_equals(ip, addr->ip))
+ {
+ name = strdup(iface->ifname);
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+ if (name)
+ {
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+
+ if (name)
+ {
+ DBG2(DBG_KNL, "%H is on interface %s", ip, name);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "%H is not a local address", ip);
+ }
+ return name;
+}
+
+/**
+ * Implementation of kernel_net_t.get_source_addr.
+ */
+static host_t* get_source_addr(private_kernel_pfroute_net_t *this,
+ host_t *dest, host_t *src)
+{
+ return NULL;
+}
+
+/**
+ * Implementation of kernel_net_t.get_nexthop.
+ */
+static host_t* get_nexthop(private_kernel_pfroute_net_t *this, host_t *dest)
+{
+ return NULL;
+}
+
+/**
+ * Implementation of kernel_net_t.add_ip.
+ */
+static status_t add_ip(private_kernel_pfroute_net_t *this,
+ host_t *virtual_ip, host_t *iface_ip)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_net_t.del_ip.
+ */
+static status_t del_ip(private_kernel_pfroute_net_t *this, host_t *virtual_ip)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_net_t.add_route.
+ */
+static status_t add_route(private_kernel_pfroute_net_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_net_t.del_route.
+ */
+static status_t del_route(private_kernel_pfroute_net_t *this, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+ return FAILED;
+}
+
+/**
+ * Initialize a list of local addresses.
+ */
+static status_t init_address_list(private_kernel_pfroute_net_t *this)
+{
+ struct ifaddrs *ifap, *ifa;
+ iface_entry_t *iface, *current;
+ addr_entry_t *addr;
+ enumerator_t *ifaces, *addrs;
+
+ DBG1(DBG_KNL, "listening on interfaces:");
+
+ if (getifaddrs(&ifap) < 0)
+ {
+ DBG1(DBG_KNL, " failed to get interfaces!");
+ return FAILED;
+ }
+
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr == NULL)
+ {
+ continue;
+ }
+ switch(ifa->ifa_addr->sa_family)
+ {
+ case AF_LINK:
+ case AF_INET:
+ case AF_INET6:
+ {
+ if (ifa->ifa_flags & IFF_LOOPBACK)
+ { /* ignore loopback interfaces */
+ continue;
+ }
+
+ iface = NULL;
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &current))
+ {
+ if (streq(current->ifname, ifa->ifa_name))
+ {
+ iface = current;
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+
+ if (!iface)
+ {
+ iface = malloc_thing(iface_entry_t);
+ memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
+ iface->ifindex = if_nametoindex(ifa->ifa_name);
+ iface->flags = ifa->ifa_flags;
+ iface->addrs = linked_list_create();
+ this->ifaces->insert_last(this->ifaces, iface);
+ }
+
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ {
+ addr = malloc_thing(addr_entry_t);
+ addr->ip = host_create_from_sockaddr(ifa->ifa_addr);
+ addr->virtual = FALSE;
+ addr->refcount = 1;
+ iface->addrs->insert_last(iface->addrs, addr);
+ }
+ }
+ }
+ }
+ freeifaddrs(ifap);
+
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->flags & IFF_UP)
+ {
+ DBG1(DBG_KNL, " %s", iface->ifname);
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, (void**)&addr))
+ {
+ DBG1(DBG_KNL, " %H", addr->ip);
+ }
+ addrs->destroy(addrs);
+ }
+ }
+ ifaces->destroy(ifaces);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_netlink_net_t.destroy.
+ */
+static void destroy(private_kernel_pfroute_net_t *this)
+{
+ if (this->job)
+ {
+ this->job->cancel(this->job);
+ }
+ if (this->socket > 0)
+ {
+ close(this->socket);
+ }
+ if (this->socket_events)
+ {
+ close(this->socket_events);
+ }
+ this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
+ this->mutex->destroy(this->mutex);
+ this->mutex_pfroute->destroy(this->mutex_pfroute);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_pfroute_net_t *kernel_pfroute_net_create()
+{
+ private_kernel_pfroute_net_t *this = malloc_thing(private_kernel_pfroute_net_t);
+
+ /* public functions */
+ this->public.interface.get_interface = (char*(*)(kernel_net_t*,host_t*))get_interface_name;
+ this->public.interface.create_address_enumerator = (enumerator_t*(*)(kernel_net_t*,bool,bool))create_address_enumerator;
+ this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest, host_t *src))get_source_addr;
+ this->public.interface.get_nexthop = (host_t*(*)(kernel_net_t*, host_t *dest))get_nexthop;
+ this->public.interface.add_ip = (status_t(*)(kernel_net_t*,host_t*,host_t*)) add_ip;
+ this->public.interface.del_ip = (status_t(*)(kernel_net_t*,host_t*)) del_ip;
+ this->public.interface.add_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) add_route;
+ this->public.interface.del_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) del_route;
+
+ this->public.interface.destroy = (void(*)(kernel_net_t*)) destroy;
+
+ /* private members */
+ this->ifaces = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->mutex_pfroute = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ this->seq = 0;
+ this->socket_events = 0;
+ this->job = NULL;
+
+ /* create a PF_ROUTE socket to communicate with the kernel */
+ this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+ if (this->socket < 0)
+ {
+ DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
+ destroy(this);
+ return NULL;
+ }
+
+ /* create a PF_ROUTE socket to receive events */
+ this->socket_events = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+ if (this->socket_events < 0)
+ {
+ DBG1(DBG_KNL, "unable to create PF_ROUTE event socket");
+ destroy(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ if (init_address_list(this) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to get interface list");
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h
new file mode 100644
index 000000000..10c3c9eb7
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_pfroute_net_i kernel_pfroute_net
+ * @{ @ingroup kernel_pfroute
+ */
+
+#ifndef KERNEL_PFROUTE_NET_H_
+#define KERNEL_PFROUTE_NET_H_
+
+#include <kernel/kernel_net.h>
+
+typedef struct kernel_pfroute_net_t kernel_pfroute_net_t;
+
+/**
+ * Implementation of the kernel net interface using PF_ROUTE.
+ */
+struct kernel_pfroute_net_t {
+
+ /**
+ * Implements kernel_net_t interface
+ */
+ kernel_net_t interface;
+};
+
+/**
+ * Create a PF_ROUTE kernel net interface instance.
+ *
+ * @return kernel_pfroute_net_t instance
+ */
+kernel_pfroute_net_t *kernel_pfroute_net_create();
+
+#endif /** KERNEL_PFROUTE_NET_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c
new file mode 100644
index 000000000..97139fb56
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "kernel_pfroute_plugin.h"
+
+#include "kernel_pfroute_net.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_pfroute_plugin_t private_kernel_pfroute_plugin_t;
+
+/**
+ * private data of kernel PF_ROUTE plugin
+ */
+struct private_kernel_pfroute_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_pfroute_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_pfroute_plugin_t *this)
+{
+ charon->kernel_interface->remove_net_interface(charon->kernel_interface,
+ (kernel_net_constructor_t)kernel_pfroute_net_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_pfroute_plugin_create()
+{
+ private_kernel_pfroute_plugin_t *this = malloc_thing(private_kernel_pfroute_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_net_interface(charon->kernel_interface,
+ (kernel_net_constructor_t)kernel_pfroute_net_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h
new file mode 100644
index 000000000..50642a572
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_pfroute kernel_pfroute
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_pfroute_plugin kernel_pfroute_plugin
+ * @{ @ingroup kernel_pfroute
+ */
+
+#ifndef KERNEL_PFROUTE_PLUGIN_H_
+#define KERNEL_PFROUTE_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_pfroute_plugin_t kernel_pfroute_plugin_t;
+
+/**
+ * PF_ROUTE kernel interface plugin
+ */
+struct kernel_pfroute_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_PFROUTE_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/Makefile.am b/src/libcharon/plugins/load_tester/Makefile.am
new file mode 100644
index 000000000..cdd0445a9
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/Makefile.am
@@ -0,0 +1,21 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-load-tester.la
+else
+plugin_LTLIBRARIES = libstrongswan-load-tester.la
+endif
+
+libstrongswan_load_tester_la_SOURCES = \
+ load_tester_plugin.c load_tester_plugin.h \
+ load_tester_config.c load_tester_config.h \
+ load_tester_creds.c load_tester_creds.h \
+ load_tester_ipsec.c load_tester_ipsec.h \
+ load_tester_listener.c load_tester_listener.h \
+ load_tester_diffie_hellman.c load_tester_diffie_hellman.h
+
+libstrongswan_load_tester_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
new file mode 100644
index 000000000..8965aff78
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -0,0 +1,600 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/load_tester
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_load_tester_la_LIBADD =
+am_libstrongswan_load_tester_la_OBJECTS = load_tester_plugin.lo \
+ load_tester_config.lo load_tester_creds.lo \
+ load_tester_ipsec.lo load_tester_listener.lo \
+ load_tester_diffie_hellman.lo
+libstrongswan_load_tester_la_OBJECTS = \
+ $(am_libstrongswan_load_tester_la_OBJECTS)
+libstrongswan_load_tester_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_load_tester_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_load_tester_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_load_tester_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_load_tester_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_load_tester_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-load-tester.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-load-tester.la
+libstrongswan_load_tester_la_SOURCES = \
+ load_tester_plugin.c load_tester_plugin.h \
+ load_tester_config.c load_tester_config.h \
+ load_tester_creds.c load_tester_creds.h \
+ load_tester_ipsec.c load_tester_ipsec.h \
+ load_tester_listener.c load_tester_listener.h \
+ load_tester_diffie_hellman.c load_tester_diffie_hellman.h
+
+libstrongswan_load_tester_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/load_tester/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/load_tester/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-load-tester.la: $(libstrongswan_load_tester_la_OBJECTS) $(libstrongswan_load_tester_la_DEPENDENCIES)
+ $(libstrongswan_load_tester_la_LINK) $(am_libstrongswan_load_tester_la_rpath) $(libstrongswan_load_tester_la_OBJECTS) $(libstrongswan_load_tester_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_diffie_hellman.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
new file mode 100644
index 000000000..c1f98f2fe
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_config.h"
+
+#include <daemon.h>
+
+typedef struct private_load_tester_config_t private_load_tester_config_t;
+
+/**
+ * Private data of an load_tester_config_t object
+ */
+struct private_load_tester_config_t {
+
+ /**
+ * Public part
+ */
+ load_tester_config_t public;
+
+ /**
+ * peer config
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * virtual IP, if any
+ */
+ host_t *vip;
+
+ /**
+ * Remote address
+ */
+ char *remote;
+
+ /**
+ * IP address pool
+ */
+ char *pool;
+
+ /**
+ * IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * Authentication method(s) to use/expect from initiator
+ */
+ char *initiator_auth;
+
+ /**
+ * Authentication method(s) use/expected from responder
+ */
+ char *responder_auth;
+
+ /**
+ * IKE_SA rekeying delay
+ */
+ u_int ike_rekey;
+
+ /**
+ * CHILD_SA rekeying delay
+ */
+ u_int child_rekey;
+
+ /**
+ * incremental numbering of generated configs
+ */
+ u_int num;
+
+ /**
+ * Dynamic source port, if used
+ */
+ u_int16_t port;
+};
+
+/**
+ * Generate auth config from string
+ */
+static void generate_auth_cfg(private_load_tester_config_t *this, char *str,
+ peer_cfg_t *peer_cfg, bool local, int num)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ identification_t *id;
+ auth_class_t class;
+ eap_type_t type;
+ char buf[128];
+ int rnd = 0;
+
+ enumerator = enumerator_create_token(str, "|", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ auth = auth_cfg_create();
+ rnd++;
+
+ if (streq(str, "psk"))
+ { /* PSK authentication, use FQDNs */
+ class = AUTH_CLASS_PSK;
+ if ((local && !num) || (!local && num))
+ {
+ id = identification_create_from_string("srv.strongswan.org");
+ }
+ else if (local)
+ {
+ snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_string("*.strongswan.org");
+ }
+ }
+ else if (strneq(str, "eap", strlen("eap")))
+ { /* EAP authentication, use a NAI */
+ class = AUTH_CLASS_EAP;
+ if (*(str + strlen("eap")) == '-')
+ {
+ type = eap_type_from_string(str + strlen("eap-"));
+ if (type)
+ {
+ auth->add(auth, AUTH_RULE_EAP_TYPE, type);
+ }
+ }
+ if (local && num)
+ {
+ snprintf(buf, sizeof(buf), "1%.10d%.4d@strongswan.org", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ }
+ }
+ else
+ {
+ if (!streq(str, "pubkey"))
+ {
+ DBG1(DBG_CFG, "invalid authentication: '%s', fallback to pubkey",
+ str);
+ }
+ /* certificate authentication, use distinguished names */
+ class = AUTH_CLASS_PUBKEY;
+ if ((local && !num) || (!local && num))
+ {
+ id = identification_create_from_string(
+ "CN=srv, OU=load-test, O=strongSwan");
+ }
+ else if (local)
+ {
+ snprintf(buf, sizeof(buf),
+ "CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_string(
+ "CN=*, OU=load-test, O=strongSwan");
+ }
+ }
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, class);
+ auth->add(auth, AUTH_RULE_IDENTITY, id);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, local);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Generate a new initiator config, num = 0 for responder config
+ */
+static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
+{
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ peer_cfg_t *peer_cfg;
+ traffic_selector_t *ts;
+ proposal_t *proposal;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = this->child_rekey * 2,
+ .rekey = this->child_rekey,
+ .jitter = 0
+ }
+ };
+
+ if (this->port && num)
+ {
+ ike_cfg = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", this->port + num - 1, this->remote, IKEV2_NATT_PORT);
+ }
+ else
+ {
+ ike_cfg = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", IKEV2_UDP_PORT, this->remote, IKEV2_UDP_PORT);
+ }
+ ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
+ peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
+ CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
+ this->ike_rekey, 0, /* rekey, reauth */
+ 0, this->ike_rekey, /* jitter, overtime */
+ FALSE, 0, /* mobike, dpddelay */
+ this->vip ? this->vip->clone(this->vip) : NULL,
+ this->pool, FALSE, NULL, NULL);
+ if (num)
+ { /* initiator */
+ generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
+ generate_auth_cfg(this, this->responder_auth, peer_cfg, FALSE, num);
+ }
+ else
+ { /* responder */
+ generate_auth_cfg(this, this->responder_auth, peer_cfg, TRUE, num);
+ generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
+ }
+
+ child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE,
+ MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
+ child_cfg->add_proposal(child_cfg, proposal);
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+ return peer_cfg;
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_load_tester_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ return enumerator_create_single(this->peer_cfg, NULL);
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_load_tester_config_t *this,
+ host_t *me, host_t *other)
+{
+ ike_cfg_t *ike_cfg;
+
+ ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
+ return enumerator_create_single(ike_cfg, NULL);
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_load_tester_config_t *this,
+ char *name)
+{
+ if (streq(name, "load-test"))
+ {
+ return generate_config(this, this->num++);
+ }
+ return NULL;
+}
+
+/**
+ * Implementation of load_tester_config_t.destroy.
+ */
+static void destroy(private_load_tester_config_t *this)
+{
+ this->peer_cfg->destroy(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->vip);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+load_tester_config_t *load_tester_config_create()
+{
+ private_load_tester_config_t *this = malloc_thing(private_load_tester_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(load_tester_config_t*))destroy;
+
+ this->vip = NULL;
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.load-tester.request_virtual_ip", FALSE))
+ {
+ this->vip = host_create_from_string("0.0.0.0", 0);
+ }
+ this->pool = lib->settings->get_str(lib->settings,
+ "charon.plugins.load-tester.pool", NULL);
+ this->remote = lib->settings->get_str(lib->settings,
+ "charon.plugins.load-tester.remote", "127.0.0.1");
+
+ this->proposal = proposal_create_from_string(PROTO_IKE,
+ lib->settings->get_str(lib->settings,
+ "charon.plugins.load-tester.proposal", "aes128-sha1-modp768"));
+ if (!this->proposal)
+ { /* fallback */
+ this->proposal = proposal_create_from_string(PROTO_IKE,
+ "aes128-sha1-modp768");
+ }
+ this->ike_rekey = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.ike_rekey", 0);
+ this->child_rekey = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.child_rekey", 600);
+
+ this->initiator_auth = lib->settings->get_str(lib->settings,
+ "charon.plugins.load-tester.initiator_auth", "pubkey");
+ this->responder_auth = lib->settings->get_str(lib->settings,
+ "charon.plugins.load-tester.responder_auth", "pubkey");
+
+ this->port = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.dynamic_port", 0);
+
+ this->num = 1;
+ this->peer_cfg = generate_config(this, 0);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.h b/src/libcharon/plugins/load_tester/load_tester_config.h
new file mode 100644
index 000000000..c22387743
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_config.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup load_tester_config_t load_tester_config
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_CONFIG_H_
+#define LOAD_TESTER_CONFIG_H_
+
+#include <config/backend.h>
+
+typedef struct load_tester_config_t load_tester_config_t;
+
+/**
+ * Provide configurations for load testing.
+ */
+struct load_tester_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_config_t *this);
+};
+
+/**
+ * Create a configuration backend for load testing.
+ *
+ * @return configuration backend
+ */
+load_tester_config_t *load_tester_config_create();
+
+#endif /** LOAD_TESTER_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c
new file mode 100644
index 000000000..890703c1a
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.c
@@ -0,0 +1,313 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_creds.h"
+
+#include <time.h>
+
+#include <daemon.h>
+#include <credentials/keys/shared_key.h>
+#include <credentials/certificates/x509.h>
+#include <utils/identification.h>
+
+typedef struct private_load_tester_creds_t private_load_tester_creds_t;
+
+/**
+ * Private data of an load_tester_creds_t object
+ */
+struct private_load_tester_creds_t {
+ /**
+ * Public part
+ */
+ load_tester_creds_t public;
+
+ /**
+ * Private key to create signatures
+ */
+ private_key_t *private;
+
+ /**
+ * CA certificate, to issue/verify peer certificates
+ */
+ certificate_t *ca;
+
+ /**
+ * serial number to issue certificates
+ */
+ u_int32_t serial;
+
+ /**
+ * Preshared key
+ */
+ shared_key_t *shared;
+};
+
+/**
+ * 1024-bit RSA key:
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDQXr7poAPYZLxmTCqR51STGRuk9Hc5SWtTcs6b2RzpnP8EVRLx
+JEVxOKE9Mw6n7mD1pNrupCpnpGRdLAV5VznTPhSQ6k7ppJJrxosRYg0pHTZqBUEC
+7nQFwAe10g8q0UnM1wa4lJzGxDH78d21cVweJgbkxAeyriS0jhNs7gO5nQIDAQAB
+AoGACVACtkxJf7VY2jWTPXwaQoy/uIqYfX3zhwI9i6eTbDlxCE+JDi/xzpKaWjLa
+99RmjvP0OPArWQB239ck03x7gAm2obutosGbqbKzJZS5cyIayzyW9djZDHBdt9Ho
+quKB39aspWit3xPzkrr+QeIkiggtmBKALTBxTwxAU+P6euECQQD4IPdrzKbCrO79
+LKvoPrQQtTjL6ogag9rI9n2ZuoK3/XVybh2byOXT8tA5G5jSz9Ac8XeVOsnH9gT5
+3WXeaLOFAkEA1vrm/hVSEasp5eATgQ7ig9CF+GGKqhTwXp/uOSl/h3IRmStu5J0C
+9AkYyx0bn3j5R8iUEX/C00KSE1kQNh4NOQJAVOsLYlRG2idPH0xThQc4nuM2jes1
+K0Xm8ZISSDNhm1BeCoyPC4rExTW7d1/vfG5svgsRrvvQpOOYrl7MB0Lz9QJBALhg
+AWJiyLsskEd90Vx7dpvUaEHo7jMGuEx/X6GYzK5Oj3dNP9NEMfc4IhJ5SWqRJ0KA
+bTVA3MexLXT4iqXPSkkCQQDSjLhBwvEnSuW4ElIMzBwLbu7573z2gzU82Mj6trrw
+Osoox/vmcepT1Wjy4AvPZHgxp7vEXNSeS+M5L29QNTp8
+-----END RSA PRIVATE KEY-----
+ */
+static char private[] = {
+ 0x30,0x82,0x02,0x5d,0x02,0x01,0x00,0x02,0x81,0x81,0x00,0xd0,0x5e,0xbe,0xe9,0xa0,
+ 0x03,0xd8,0x64,0xbc,0x66,0x4c,0x2a,0x91,0xe7,0x54,0x93,0x19,0x1b,0xa4,0xf4,0x77,
+ 0x39,0x49,0x6b,0x53,0x72,0xce,0x9b,0xd9,0x1c,0xe9,0x9c,0xff,0x04,0x55,0x12,0xf1,
+ 0x24,0x45,0x71,0x38,0xa1,0x3d,0x33,0x0e,0xa7,0xee,0x60,0xf5,0xa4,0xda,0xee,0xa4,
+ 0x2a,0x67,0xa4,0x64,0x5d,0x2c,0x05,0x79,0x57,0x39,0xd3,0x3e,0x14,0x90,0xea,0x4e,
+ 0xe9,0xa4,0x92,0x6b,0xc6,0x8b,0x11,0x62,0x0d,0x29,0x1d,0x36,0x6a,0x05,0x41,0x02,
+ 0xee,0x74,0x05,0xc0,0x07,0xb5,0xd2,0x0f,0x2a,0xd1,0x49,0xcc,0xd7,0x06,0xb8,0x94,
+ 0x9c,0xc6,0xc4,0x31,0xfb,0xf1,0xdd,0xb5,0x71,0x5c,0x1e,0x26,0x06,0xe4,0xc4,0x07,
+ 0xb2,0xae,0x24,0xb4,0x8e,0x13,0x6c,0xee,0x03,0xb9,0x9d,0x02,0x03,0x01,0x00,0x01,
+ 0x02,0x81,0x80,0x09,0x50,0x02,0xb6,0x4c,0x49,0x7f,0xb5,0x58,0xda,0x35,0x93,0x3d,
+ 0x7c,0x1a,0x42,0x8c,0xbf,0xb8,0x8a,0x98,0x7d,0x7d,0xf3,0x87,0x02,0x3d,0x8b,0xa7,
+ 0x93,0x6c,0x39,0x71,0x08,0x4f,0x89,0x0e,0x2f,0xf1,0xce,0x92,0x9a,0x5a,0x32,0xda,
+ 0xf7,0xd4,0x66,0x8e,0xf3,0xf4,0x38,0xf0,0x2b,0x59,0x00,0x76,0xdf,0xd7,0x24,0xd3,
+ 0x7c,0x7b,0x80,0x09,0xb6,0xa1,0xbb,0xad,0xa2,0xc1,0x9b,0xa9,0xb2,0xb3,0x25,0x94,
+ 0xb9,0x73,0x22,0x1a,0xcb,0x3c,0x96,0xf5,0xd8,0xd9,0x0c,0x70,0x5d,0xb7,0xd1,0xe8,
+ 0xaa,0xe2,0x81,0xdf,0xd6,0xac,0xa5,0x68,0xad,0xdf,0x13,0xf3,0x92,0xba,0xfe,0x41,
+ 0xe2,0x24,0x8a,0x08,0x2d,0x98,0x12,0x80,0x2d,0x30,0x71,0x4f,0x0c,0x40,0x53,0xe3,
+ 0xfa,0x7a,0xe1,0x02,0x41,0x00,0xf8,0x20,0xf7,0x6b,0xcc,0xa6,0xc2,0xac,0xee,0xfd,
+ 0x2c,0xab,0xe8,0x3e,0xb4,0x10,0xb5,0x38,0xcb,0xea,0x88,0x1a,0x83,0xda,0xc8,0xf6,
+ 0x7d,0x99,0xba,0x82,0xb7,0xfd,0x75,0x72,0x6e,0x1d,0x9b,0xc8,0xe5,0xd3,0xf2,0xd0,
+ 0x39,0x1b,0x98,0xd2,0xcf,0xd0,0x1c,0xf1,0x77,0x95,0x3a,0xc9,0xc7,0xf6,0x04,0xf9,
+ 0xdd,0x65,0xde,0x68,0xb3,0x85,0x02,0x41,0x00,0xd6,0xfa,0xe6,0xfe,0x15,0x52,0x11,
+ 0xab,0x29,0xe5,0xe0,0x13,0x81,0x0e,0xe2,0x83,0xd0,0x85,0xf8,0x61,0x8a,0xaa,0x14,
+ 0xf0,0x5e,0x9f,0xee,0x39,0x29,0x7f,0x87,0x72,0x11,0x99,0x2b,0x6e,0xe4,0x9d,0x02,
+ 0xf4,0x09,0x18,0xcb,0x1d,0x1b,0x9f,0x78,0xf9,0x47,0xc8,0x94,0x11,0x7f,0xc2,0xd3,
+ 0x42,0x92,0x13,0x59,0x10,0x36,0x1e,0x0d,0x39,0x02,0x40,0x54,0xeb,0x0b,0x62,0x54,
+ 0x46,0xda,0x27,0x4f,0x1f,0x4c,0x53,0x85,0x07,0x38,0x9e,0xe3,0x36,0x8d,0xeb,0x35,
+ 0x2b,0x45,0xe6,0xf1,0x92,0x12,0x48,0x33,0x61,0x9b,0x50,0x5e,0x0a,0x8c,0x8f,0x0b,
+ 0x8a,0xc4,0xc5,0x35,0xbb,0x77,0x5f,0xef,0x7c,0x6e,0x6c,0xbe,0x0b,0x11,0xae,0xfb,
+ 0xd0,0xa4,0xe3,0x98,0xae,0x5e,0xcc,0x07,0x42,0xf3,0xf5,0x02,0x41,0x00,0xb8,0x60,
+ 0x01,0x62,0x62,0xc8,0xbb,0x2c,0x90,0x47,0x7d,0xd1,0x5c,0x7b,0x76,0x9b,0xd4,0x68,
+ 0x41,0xe8,0xee,0x33,0x06,0xb8,0x4c,0x7f,0x5f,0xa1,0x98,0xcc,0xae,0x4e,0x8f,0x77,
+ 0x4d,0x3f,0xd3,0x44,0x31,0xf7,0x38,0x22,0x12,0x79,0x49,0x6a,0x91,0x27,0x42,0x80,
+ 0x6d,0x35,0x40,0xdc,0xc7,0xb1,0x2d,0x74,0xf8,0x8a,0xa5,0xcf,0x4a,0x49,0x02,0x41,
+ 0x00,0xd2,0x8c,0xb8,0x41,0xc2,0xf1,0x27,0x4a,0xe5,0xb8,0x12,0x52,0x0c,0xcc,0x1c,
+ 0x0b,0x6e,0xee,0xf9,0xef,0x7c,0xf6,0x83,0x35,0x3c,0xd8,0xc8,0xfa,0xb6,0xba,0xf0,
+ 0x3a,0xca,0x28,0xc7,0xfb,0xe6,0x71,0xea,0x53,0xd5,0x68,0xf2,0xe0,0x0b,0xcf,0x64,
+ 0x78,0x31,0xa7,0xbb,0xc4,0x5c,0xd4,0x9e,0x4b,0xe3,0x39,0x2f,0x6f,0x50,0x35,0x3a,
+ 0x7c,
+};
+
+/**
+ * And an associated self-signed certificate
+-----BEGIN CERTIFICATE-----
+MIIB9DCCAV2gAwIBAgIBADANBgkqhkiG9w0BAQUFADA3MQwwCgYDVQQDEwNzcnYx
+EjAQBgNVBAsTCWxvYWQtdGVzdDETMBEGA1UEChMKc3Ryb25nU3dhbjAeFw0wODEy
+MDgxODU4NDhaFw0xODEyMDYxODU4NDhaMDcxDDAKBgNVBAMTA3NydjESMBAGA1UE
+CxMJbG9hZC10ZXN0MRMwEQYDVQQKEwpzdHJvbmdTd2FuMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDQXr7poAPYZLxmTCqR51STGRuk9Hc5SWtTcs6b2RzpnP8E
+VRLxJEVxOKE9Mw6n7mD1pNrupCpnpGRdLAV5VznTPhSQ6k7ppJJrxosRYg0pHTZq
+BUEC7nQFwAe10g8q0UnM1wa4lJzGxDH78d21cVweJgbkxAeyriS0jhNs7gO5nQID
+AQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAF39Xedyk2wj
+qOcaaZ7ypb8RDlLvS0uaJMVtLtIhtb2weMMlgdmOnKXEYrJL2/mbp14Fhe+XYME9
+nZLAnmUnX8bQWCsQlajb7YGE8w6QDMwXUVgSXTMhRl+PRX2CMIUzU21h1EIx65Po
+CwMLbJ7vQqwPHXRitDmNkEOK9H+vRnDf
+-----END CERTIFICATE-----
+
+ */
+char cert[] = {
+ 0x30,0x82,0x01,0xf4,0x30,0x82,0x01,0x5d,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x00,
+ 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,
+ 0x37,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x73,0x72,0x76,0x31,
+ 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x0b,0x13,0x09,0x6c,0x6f,0x61,0x64,0x2d,0x74,
+ 0x65,0x73,0x74,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x73,0x74,
+ 0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x30,0x1e,0x17,0x0d,0x30,0x38,0x31,0x32,
+ 0x30,0x38,0x31,0x38,0x35,0x38,0x34,0x38,0x5a,0x17,0x0d,0x31,0x38,0x31,0x32,0x30,
+ 0x36,0x31,0x38,0x35,0x38,0x34,0x38,0x5a,0x30,0x37,0x31,0x0c,0x30,0x0a,0x06,0x03,
+ 0x55,0x04,0x03,0x13,0x03,0x73,0x72,0x76,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,
+ 0x0b,0x13,0x09,0x6c,0x6f,0x61,0x64,0x2d,0x74,0x65,0x73,0x74,0x31,0x13,0x30,0x11,
+ 0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,
+ 0x6e,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
+ 0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd0,0x5e,
+ 0xbe,0xe9,0xa0,0x03,0xd8,0x64,0xbc,0x66,0x4c,0x2a,0x91,0xe7,0x54,0x93,0x19,0x1b,
+ 0xa4,0xf4,0x77,0x39,0x49,0x6b,0x53,0x72,0xce,0x9b,0xd9,0x1c,0xe9,0x9c,0xff,0x04,
+ 0x55,0x12,0xf1,0x24,0x45,0x71,0x38,0xa1,0x3d,0x33,0x0e,0xa7,0xee,0x60,0xf5,0xa4,
+ 0xda,0xee,0xa4,0x2a,0x67,0xa4,0x64,0x5d,0x2c,0x05,0x79,0x57,0x39,0xd3,0x3e,0x14,
+ 0x90,0xea,0x4e,0xe9,0xa4,0x92,0x6b,0xc6,0x8b,0x11,0x62,0x0d,0x29,0x1d,0x36,0x6a,
+ 0x05,0x41,0x02,0xee,0x74,0x05,0xc0,0x07,0xb5,0xd2,0x0f,0x2a,0xd1,0x49,0xcc,0xd7,
+ 0x06,0xb8,0x94,0x9c,0xc6,0xc4,0x31,0xfb,0xf1,0xdd,0xb5,0x71,0x5c,0x1e,0x26,0x06,
+ 0xe4,0xc4,0x07,0xb2,0xae,0x24,0xb4,0x8e,0x13,0x6c,0xee,0x03,0xb9,0x9d,0x02,0x03,
+ 0x01,0x00,0x01,0xa3,0x10,0x30,0x0e,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x04,0x05,
+ 0x30,0x03,0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
+ 0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x5d,0xfd,0x5d,0xe7,0x72,0x93,0x6c,0x23,
+ 0xa8,0xe7,0x1a,0x69,0x9e,0xf2,0xa5,0xbf,0x11,0x0e,0x52,0xef,0x4b,0x4b,0x9a,0x24,
+ 0xc5,0x6d,0x2e,0xd2,0x21,0xb5,0xbd,0xb0,0x78,0xc3,0x25,0x81,0xd9,0x8e,0x9c,0xa5,
+ 0xc4,0x62,0xb2,0x4b,0xdb,0xf9,0x9b,0xa7,0x5e,0x05,0x85,0xef,0x97,0x60,0xc1,0x3d,
+ 0x9d,0x92,0xc0,0x9e,0x65,0x27,0x5f,0xc6,0xd0,0x58,0x2b,0x10,0x95,0xa8,0xdb,0xed,
+ 0x81,0x84,0xf3,0x0e,0x90,0x0c,0xcc,0x17,0x51,0x58,0x12,0x5d,0x33,0x21,0x46,0x5f,
+ 0x8f,0x45,0x7d,0x82,0x30,0x85,0x33,0x53,0x6d,0x61,0xd4,0x42,0x31,0xeb,0x93,0xe8,
+ 0x0b,0x03,0x0b,0x6c,0x9e,0xef,0x42,0xac,0x0f,0x1d,0x74,0x62,0xb4,0x39,0x8d,0x90,
+ 0x43,0x8a,0xf4,0x7f,0xaf,0x46,0x70,0xdf,
+};
+
+
+/**
+ * A preshared key
+ */
+static char psk[] = {
+ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
+};
+
+/**
+ * Implements credential_set_t.create_private_enumerator
+ */
+static enumerator_t* create_private_enumerator(private_load_tester_creds_t *this,
+ key_type_t type, identification_t *id)
+{
+ if (this->private == NULL)
+ {
+ return NULL;
+ }
+ if (type != KEY_ANY && type != KEY_RSA)
+ {
+ return NULL;
+ }
+ if (id)
+ {
+ if (!this->private->has_fingerprint(this->private, id->get_encoding(id)))
+ {
+ return NULL;
+ }
+ }
+ return enumerator_create_single(this->private, NULL);
+}
+
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_cert_enumerator(private_load_tester_creds_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ certificate_t *peer_cert;
+ public_key_t *peer_key, *ca_key;
+ u_int32_t serial;
+ time_t now;
+
+ if (this->ca == NULL)
+ {
+ return NULL;
+ }
+ if (cert != CERT_ANY && cert != CERT_X509)
+ {
+ return NULL;
+ }
+ if (key != KEY_ANY && key != KEY_RSA)
+ {
+ return NULL;
+ }
+ if (!id)
+ {
+ return enumerator_create_single(this->ca, NULL);
+ }
+ ca_key = this->ca->get_public_key(this->ca);
+ if (ca_key)
+ {
+ if (ca_key->has_fingerprint(ca_key, id->get_encoding(id)))
+ {
+ ca_key->destroy(ca_key);
+ return enumerator_create_single(this->ca, NULL);
+ }
+ ca_key->destroy(ca_key);
+ }
+ if (this->ca->has_subject(this->ca, id))
+ {
+ return enumerator_create_single(this->ca, NULL);
+ }
+ if (!trusted)
+ {
+ /* peer certificate, generate on demand */
+ serial = htonl(++this->serial);
+ now = time(NULL);
+ peer_key = this->private->get_public_key(this->private);
+ peer_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_SIGNING_KEY, this->private,
+ BUILD_SIGNING_CERT, this->ca,
+ BUILD_PUBLIC_KEY, peer_key,
+ BUILD_SUBJECT, id,
+ BUILD_NOT_BEFORE_TIME, now - 60 * 60 * 24,
+ BUILD_NOT_AFTER_TIME, now + 60 * 60 * 24,
+ BUILD_SERIAL, chunk_from_thing(serial),
+ BUILD_END);
+ peer_key->destroy(peer_key);
+ if (peer_cert)
+ {
+ return enumerator_create_single(peer_cert, (void*)peer_cert->destroy);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Implements credential_set_t.create_shared_enumerator
+ */
+static enumerator_t* create_shared_enumerator(private_load_tester_creds_t *this,
+ shared_key_type_t type, identification_t *me,
+ identification_t *other)
+{
+ return enumerator_create_single(this->shared, NULL);
+}
+
+/**
+ * Implementation of load_tester_creds_t.destroy
+ */
+static void destroy(private_load_tester_creds_t *this)
+{
+ DESTROY_IF(this->private);
+ DESTROY_IF(this->ca);
+ this->shared->destroy(this->shared);
+ free(this);
+}
+
+load_tester_creds_t *load_tester_creds_create()
+{
+ private_load_tester_creds_t *this = malloc_thing(private_load_tester_creds_t);
+
+ this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))create_shared_enumerator;
+ this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))create_private_enumerator;
+ this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))create_cert_enumerator;
+ this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null;
+ this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop;
+ this->public.destroy = (void(*) (load_tester_creds_t*))destroy;
+
+ this->private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk_create(private, sizeof(private)),
+ BUILD_END);
+
+ this->ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, chunk_create(cert, sizeof(cert)),
+ BUILD_X509_FLAG, X509_CA,
+ BUILD_END);
+
+ this->shared = shared_key_create(SHARED_IKE,
+ chunk_clone(chunk_create(psk, sizeof(psk))));
+ this->serial = 0;
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.h b/src/libcharon/plugins/load_tester/load_tester_creds.h
new file mode 100644
index 000000000..fb3541164
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup load_tester_creds_t load_tester_creds
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_CREDS_H_
+#define LOAD_TESTER_CREDS_H_
+
+#include <credentials/credential_set.h>
+
+typedef struct load_tester_creds_t load_tester_creds_t;
+
+/**
+ * Provide hard-coded credentials for load testing.
+ */
+struct load_tester_creds_t {
+
+ /**
+ * Implements credential set interface.
+ */
+ credential_set_t credential_set;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_creds_t *this);
+};
+
+/**
+ * Create a credential set for load testing.
+ *
+ * @return credential set
+ */
+load_tester_creds_t *load_tester_creds_create();
+
+#endif /** LOAD_TESTER_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c
new file mode 100644
index 000000000..d5ec3599b
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_diffie_hellman.h"
+
+/**
+ * Implementation of gmp_diffie_hellman_t.get_my_public_value.
+ */
+static void get_my_public_value(load_tester_diffie_hellman_t *this,
+ chunk_t *value)
+{
+ *value = chunk_empty;
+}
+
+/**
+ * Implementation of gmp_diffie_hellman_t.get_shared_secret.
+ */
+static status_t get_shared_secret(load_tester_diffie_hellman_t *this,
+ chunk_t *secret)
+{
+ *secret = chunk_empty;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of gmp_diffie_hellman_t.get_dh_group.
+ */
+static diffie_hellman_group_t get_dh_group(load_tester_diffie_hellman_t *this)
+{
+ return MODP_NULL;
+}
+
+/**
+ * See header
+ */
+load_tester_diffie_hellman_t *load_tester_diffie_hellman_create(
+ diffie_hellman_group_t group)
+{
+ load_tester_diffie_hellman_t *this;
+
+ if (group != MODP_NULL)
+ {
+ return NULL;
+ }
+
+ this = malloc_thing(load_tester_diffie_hellman_t);
+
+ this->dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *))get_shared_secret;
+ this->dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t ))nop;
+ this->dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *))get_my_public_value;
+ this->dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *))get_dh_group;
+ this->dh.destroy = (void (*)(diffie_hellman_t *))free;
+
+ return this;
+}
diff --git a/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.h b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.h
new file mode 100644
index 000000000..672157fb8
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup load_tester_diffie_hellman load_tester_diffie_hellman
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_DIFFIE_HELLMAN_H_
+#define LOAD_TESTER_DIFFIE_HELLMAN_H_
+
+#include <crypto/diffie_hellman.h>
+
+typedef struct load_tester_diffie_hellman_t load_tester_diffie_hellman_t;
+
+/**
+ * A NULL Diffie Hellman implementation to avoid calculation overhead in tests.
+ */
+struct load_tester_diffie_hellman_t {
+
+ /**
+ * Implements diffie_hellman_t interface.
+ */
+ diffie_hellman_t dh;
+};
+
+/**
+ * Creates a new gmp_diffie_hellman_t object.
+ *
+ * @param group Diffie Hellman group, supports MODP_NULL only
+ * @return gmp_diffie_hellman_t object
+ */
+load_tester_diffie_hellman_t *load_tester_diffie_hellman_create(
+ diffie_hellman_group_t group);
+
+#endif /** LOAD_TESTER_DIFFIE_HELLMAN_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
new file mode 100644
index 000000000..1218443cc
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_ipsec.h"
+
+#include <time.h>
+
+typedef struct private_load_tester_ipsec_t private_load_tester_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_pfkey class.
+ */
+struct private_load_tester_ipsec_t {
+ /**
+ * Public interface.
+ */
+ load_tester_ipsec_t public;
+
+ /**
+ * faked SPI counter
+ */
+ u_int32_t spi;
+};
+
+/**
+ * Implementation of kernel_interface_t.get_spi.
+ */
+static status_t get_spi(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t *spi)
+{
+ *spi = ++this->spi;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_cpi.
+ */
+static status_t get_cpi(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_sa.
+ */
+static status_t add_sa(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ 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 encap, bool inbound, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.update_sa.
+ */
+static status_t update_sa(private_load_tester_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.query_sa.
+ */
+static status_t query_sa(private_load_tester_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int64_t *bytes)
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_sa.
+ */
+static status_t del_sa(private_load_tester_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int16_t cpi)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_policy.
+ */
+static status_t add_policy(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.query_policy.
+ */
+static status_t query_policy(private_load_tester_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time)
+{
+ *use_time = time_monotonic(NULL);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_policy.
+ */
+static status_t del_policy(private_load_tester_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, bool unrouted)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.destroy.
+ */
+static void destroy(private_load_tester_ipsec_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+load_tester_ipsec_t *load_tester_ipsec_create()
+{
+ private_load_tester_ipsec_t *this = malloc_thing(private_load_tester_ipsec_t);
+
+ /* public functions */
+ this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
+ this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
+ this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
+ this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t *this,host_t *, host_t *,traffic_selector_t *,traffic_selector_t *,policy_dir_t, u_int32_t,protocol_id_t, u_int32_t,ipsec_mode_t, u_int16_t, u_int16_t,bool))add_policy;
+ this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
+ this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
+ this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
+
+ this->spi = 0;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.h b/src/libcharon/plugins/load_tester/load_tester_ipsec.h
new file mode 100644
index 000000000..1e1bff84a
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.h
@@ -0,0 +1,46 @@
+/*
+ * 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 load_tester_ipsec_i load_tester_ipsec
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_IPSEC_H_
+#define LOAD_TESTER_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct load_tester_ipsec_t load_tester_ipsec_t;
+
+/**
+ * Implementation of a fake kernel ipsec interface for load testing.
+ */
+struct load_tester_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a faked kernel ipsec interface instance.
+ *
+ * @return kernel_load_tester_ipsec_t instance
+ */
+load_tester_ipsec_t *load_tester_ipsec_create();
+
+#endif /** LOAD_TESTER_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_listener.c b/src/libcharon/plugins/load_tester/load_tester_listener.c
new file mode 100644
index 000000000..96b0cf1ec
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_listener.c
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_listener.h"
+
+#include <signal.h>
+
+#include <daemon.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+typedef struct private_load_tester_listener_t private_load_tester_listener_t;
+
+/**
+ * Private data of an load_tester_listener_t object
+ */
+struct private_load_tester_listener_t {
+ /**
+ * Public part
+ */
+ load_tester_listener_t public;
+
+ /**
+ * Delete IKE_SA after it has been established
+ */
+ bool delete_after_established;
+
+ /**
+ * Number of established SAs
+ */
+ u_int established;
+
+ /**
+ * Shutdown the daemon if we have established this SA count
+ */
+ u_int shutdown_on;
+};
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(private_load_tester_listener_t *this,
+ ike_sa_t *ike_sa, ike_sa_state_t state)
+{
+ if (state == IKE_ESTABLISHED)
+ {
+ ike_sa_id_t *id = ike_sa->get_id(ike_sa);
+
+ if (this->delete_after_established)
+ {
+ charon->processor->queue_job(charon->processor,
+ (job_t*)delete_ike_sa_job_create(id, TRUE));
+ }
+
+ if (id->is_initiator(id))
+ {
+ if (this->shutdown_on == ++this->established)
+ {
+ DBG1(DBG_CFG, "load-test complete, raising SIGTERM");
+ kill(0, SIGTERM);
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of load_tester_listener_t.destroy
+ */
+static void destroy(private_load_tester_listener_t *this)
+{
+ free(this);
+}
+
+load_tester_listener_t *load_tester_listener_create(u_int shutdown_on)
+{
+ private_load_tester_listener_t *this = malloc_thing(private_load_tester_listener_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.ike_state_change = (void*)ike_state_change;
+ this->public.destroy = (void(*) (load_tester_listener_t*))destroy;
+
+ this->delete_after_established = lib->settings->get_bool(lib->settings,
+ "charon.plugins.load-tester.delete_after_established", FALSE);
+
+ this->shutdown_on = shutdown_on;
+ this->established = 0;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/load_tester/load_tester_listener.h b/src/libcharon/plugins/load_tester/load_tester_listener.h
new file mode 100644
index 000000000..b9599294c
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_listener.h
@@ -0,0 +1,52 @@
+/*
+ * 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 load_tester_listener_t load_tester_listener
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_LISTENER_H_
+#define LOAD_TESTER_LISTENER_H_
+
+#include <bus/bus.h>
+
+typedef struct load_tester_listener_t load_tester_listener_t;
+
+/**
+ * Provide hard-coded credentials for load testing.
+ */
+struct load_tester_listener_t {
+
+ /**
+ * Implements listener set interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_listener_t *this);
+};
+
+/**
+ * Create a listener to handle special events during load test
+ *
+ * @param shutdown_on shut down the daemon after this many SAs are established
+ * @return listener
+ */
+load_tester_listener_t *load_tester_listener_create(u_int shutdown_on);
+
+#endif /** LOAD_TESTER_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
new file mode 100644
index 000000000..46145b803
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+
+#include "load_tester_plugin.h"
+#include "load_tester_config.h"
+#include "load_tester_creds.h"
+#include "load_tester_ipsec.h"
+#include "load_tester_listener.h"
+#include "load_tester_diffie_hellman.h"
+
+#include <unistd.h>
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+typedef struct private_load_tester_plugin_t private_load_tester_plugin_t;
+
+/**
+ * private data of load_tester plugin
+ */
+struct private_load_tester_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ load_tester_plugin_t public;
+
+ /**
+ * load_tester configuration backend
+ */
+ load_tester_config_t *config;
+
+ /**
+ * load_tester credential set implementation
+ */
+ load_tester_creds_t *creds;
+
+ /**
+ * event handler, listens on bus
+ */
+ load_tester_listener_t *listener;
+
+ /**
+ * number of iterations per thread
+ */
+ int iterations;
+
+ /**
+ * number desired initiator threads
+ */
+ int initiators;
+
+ /**
+ * currenly running initiators
+ */
+ int running;
+
+ /**
+ * delay between initiations, in ms
+ */
+ int delay;
+
+ /**
+ * mutex to lock running field
+ */
+ mutex_t *mutex;
+
+ /**
+ * condvar to wait for initiators
+ */
+ condvar_t *condvar;
+};
+
+/**
+ * Begin the load test
+ */
+static job_requeue_t do_load_test(private_load_tester_plugin_t *this)
+{
+ int i, s = 0, ms = 0;
+
+ this->mutex->lock(this->mutex);
+ if (!this->running)
+ {
+ this->running = this->initiators;
+ }
+ this->mutex->unlock(this->mutex);
+ if (this->delay)
+ {
+ s = this->delay / 1000;
+ ms = this->delay % 1000;
+ }
+
+ for (i = 0; this->iterations == 0 || i < this->iterations; i++)
+ {
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg = NULL;
+ enumerator_t *enumerator;
+
+ peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
+ "load-test");
+ if (!peer_cfg)
+ {
+ break;
+ }
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ if (!enumerator->enumerate(enumerator, &child_cfg))
+ {
+ enumerator->destroy(enumerator);
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ charon->controller->initiate(charon->controller,
+ peer_cfg, child_cfg->get_ref(child_cfg),
+ NULL, NULL);
+ if (s)
+ {
+ sleep(s);
+ }
+ if (ms)
+ {
+ usleep(ms * 1000);
+ }
+ }
+ this->mutex->lock(this->mutex);
+ this->running--;
+ this->mutex->unlock(this->mutex);
+ this->condvar->signal(this->condvar);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_load_tester_plugin_t *this)
+{
+ this->iterations = -1;
+ this->mutex->lock(this->mutex);
+ while (this->running)
+ {
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface,
+ (kernel_ipsec_constructor_t)load_tester_ipsec_create);
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->creds->credential_set);
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->listener->destroy(this->listener);
+ lib->crypto->remove_dh(lib->crypto,
+ (dh_constructor_t)load_tester_diffie_hellman_create);
+ this->mutex->destroy(this->mutex);
+ this->condvar->destroy(this->condvar);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *load_tester_plugin_create()
+{
+ private_load_tester_plugin_t *this;
+ u_int i, shutdown_on = 0;
+
+ if (!lib->settings->get_bool(lib->settings,
+ "charon.plugins.load-tester.enable", FALSE))
+ {
+ DBG1(DBG_CFG, "disabling load-tester plugin, not configured");
+ return NULL;
+ }
+
+ this = malloc_thing(private_load_tester_plugin_t);
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ lib->crypto->add_dh(lib->crypto, MODP_NULL,
+ (dh_constructor_t)load_tester_diffie_hellman_create);
+
+ this->delay = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.delay", 0);
+ this->iterations = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.iterations", 1);
+ this->initiators = lib->settings->get_int(lib->settings,
+ "charon.plugins.load-tester.initiators", 0);
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.load-tester.shutdown_when_complete", 0))
+ {
+ shutdown_on = this->iterations * this->initiators;
+ }
+
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->config = load_tester_config_create();
+ this->creds = load_tester_creds_create();
+ this->listener = load_tester_listener_create(shutdown_on);
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.load-tester.fake_kernel", FALSE))
+ {
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface,
+ (kernel_ipsec_constructor_t)load_tester_ipsec_create);
+ }
+ this->running = 0;
+ for (i = 0; i < this->initiators; i++)
+ {
+ charon->processor->queue_job(charon->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)do_load_test,
+ this, NULL, NULL));
+ }
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.h b/src/libcharon/plugins/load_tester/load_tester_plugin.h
new file mode 100644
index 000000000..15f2d1127
--- /dev/null
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.h
@@ -0,0 +1,44 @@
+/*
+ * 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 load_tester load_tester
+ * @ingroup cplugins
+ *
+ * @defgroup load_tester_plugin load_tester_plugin
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_PLUGIN_H_
+#define LOAD_TESTER_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct load_tester_plugin_t load_tester_plugin_t;
+
+/**
+ * Load tester plugin to inspect system core under high load.
+ *
+ * This plugin
+ */
+struct load_tester_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** LOAD_TESTER_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/medcli/Makefile.am b/src/libcharon/plugins/medcli/Makefile.am
new file mode 100644
index 000000000..cdff8d854
--- /dev/null
+++ b/src/libcharon/plugins/medcli/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-medcli.la
+else
+plugin_LTLIBRARIES = libstrongswan-medcli.la
+endif
+
+libstrongswan_medcli_la_SOURCES = \
+ medcli_plugin.h medcli_plugin.c \
+ medcli_creds.h medcli_creds.c \
+ medcli_config.h medcli_config.c \
+ medcli_listener.h medcli_listener.c
+
+libstrongswan_medcli_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
new file mode 100644
index 000000000..539890ec3
--- /dev/null
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -0,0 +1,593 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/medcli
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_medcli_la_LIBADD =
+am_libstrongswan_medcli_la_OBJECTS = medcli_plugin.lo medcli_creds.lo \
+ medcli_config.lo medcli_listener.lo
+libstrongswan_medcli_la_OBJECTS = \
+ $(am_libstrongswan_medcli_la_OBJECTS)
+libstrongswan_medcli_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_medcli_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_medcli_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_medcli_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_medcli_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_medcli_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-medcli.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-medcli.la
+libstrongswan_medcli_la_SOURCES = \
+ medcli_plugin.h medcli_plugin.c \
+ medcli_creds.h medcli_creds.c \
+ medcli_config.h medcli_config.c \
+ medcli_listener.h medcli_listener.c
+
+libstrongswan_medcli_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/medcli/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/medcli/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-medcli.la: $(libstrongswan_medcli_la_OBJECTS) $(libstrongswan_medcli_la_DEPENDENCIES)
+ $(libstrongswan_medcli_la_LINK) $(am_libstrongswan_medcli_la_rpath) $(libstrongswan_medcli_la_OBJECTS) $(libstrongswan_medcli_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
new file mode 100644
index 000000000..e355d55f7
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -0,0 +1,407 @@
+/*
+ * 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 "medcli_config.h"
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_medcli_config_t private_medcli_config_t;
+
+/**
+ * Private data of an medcli_config_t object
+ */
+struct private_medcli_config_t {
+
+ /**
+ * Public part
+ */
+ medcli_config_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+
+ /**
+ * rekey time
+ */
+ int rekey;
+
+ /**
+ * dpd delay
+ */
+ int dpd;
+
+ /**
+ * default ike config
+ */
+ ike_cfg_t *ike;
+};
+
+/**
+ * create a traffic selector from a CIDR notation string
+ */
+static traffic_selector_t *ts_from_string(char *str)
+{
+ if (str)
+ {
+ int netbits = 32;
+ host_t *net;
+ char *pos;
+
+ str = strdupa(str);
+ pos = strchr(str, '/');
+ if (pos)
+ {
+ *pos++ = '\0';
+ netbits = atoi(pos);
+ }
+ else
+ {
+ if (strchr(str, ':'))
+ {
+ netbits = 128;
+ }
+ }
+ net = host_create_from_string(str, 0);
+ if (net)
+ {
+ return traffic_selector_create_from_subnet(net, netbits, 0, 0);
+ }
+ }
+ return traffic_selector_create_dynamic(0, 0, 65535);
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *name)
+{
+ enumerator_t *e;
+ peer_cfg_t *peer_cfg, *med_cfg;
+ auth_cfg_t *auth;
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ chunk_t me, other;
+ char *address, *local_net, *remote_net;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = this->rekey * 60 + this->rekey,
+ .rekey = this->rekey,
+ .jitter = this->rekey
+ }
+ };
+
+ /* query mediation server config:
+ * - build ike_cfg/peer_cfg for mediation connection on-the-fly
+ */
+ e = this->db->query(this->db,
+ "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId "
+ "FROM MediationServerConfig JOIN ClientConfig",
+ DB_TEXT, DB_BLOB, DB_BLOB);
+ if (!e || !e->enumerate(e, &address, &me, &other))
+ {
+ DESTROY_IF(e);
+ return NULL;
+ }
+ ike_cfg = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", IKEV2_UDP_PORT, address, IKEV2_UDP_PORT);
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ med_cfg = peer_cfg_create(
+ "mediation", 2, ike_cfg,
+ CERT_NEVER_SEND, UNIQUE_REPLACE,
+ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
+ this->rekey*5, this->rekey*3, /* jitter, overtime */
+ TRUE, this->dpd, /* mobike, dpddelay */
+ NULL, NULL, /* vip, pool */
+ TRUE, NULL, NULL); /* mediation, med by, peer id */
+ e->destroy(e);
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, me));
+ med_cfg->add_auth_cfg(med_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, other));
+ med_cfg->add_auth_cfg(med_cfg, auth, FALSE);
+
+ /* query mediated config:
+ * - use any-any ike_cfg
+ * - build peer_cfg on-the-fly using med_cfg
+ * - add a child_cfg
+ */
+ e = this->db->query(this->db,
+ "SELECT ClientConfig.KeyId, Connection.KeyId, "
+ "Connection.LocalSubnet, Connection.RemoteSubnet "
+ "FROM ClientConfig JOIN Connection "
+ "WHERE Active AND Alias = ?", DB_TEXT, name,
+ DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT);
+ if (!e || !e->enumerate(e, &me, &other, &local_net, &remote_net))
+ {
+ DESTROY_IF(e);
+ return NULL;
+ }
+ peer_cfg = peer_cfg_create(
+ name, 2, this->ike->get_ref(this->ike),
+ CERT_NEVER_SEND, UNIQUE_REPLACE,
+ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
+ this->rekey*5, this->rekey*3, /* jitter, overtime */
+ TRUE, this->dpd, /* mobike, dpddelay */
+ NULL, NULL, /* vip, pool */
+ FALSE, med_cfg, /* mediation, med by */
+ identification_create_from_encoding(ID_KEY_ID, other));
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, me));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, other));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
+ child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE,
+ MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg->add_proposal(child_cfg, proposal_create_default(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);
+ e->destroy(e);
+ return peer_cfg;
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_medcli_config_t *this,
+ host_t *me, host_t *other)
+{
+ return enumerator_create_single(this->ike, NULL);
+}
+
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated peer config */
+ peer_cfg_t *current;
+ /** ike cfg to use in peer cfg */
+ ike_cfg_t *ike;
+ /** rekey time */
+ int rekey;
+ /** dpd time */
+ int dpd;
+} peer_enumerator_t;
+
+/**
+ * Implementation of peer_enumerator_t.public.enumerate
+ */
+static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
+{
+ char *name, *local_net, *remote_net;
+ chunk_t me, other;
+ child_cfg_t *child_cfg;
+ auth_cfg_t *auth;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = this->rekey * 60 + this->rekey,
+ .rekey = this->rekey,
+ .jitter = this->rekey
+ }
+ };
+
+ DESTROY_IF(this->current);
+ if (!this->inner->enumerate(this->inner, &name, &me, &other,
+ &local_net, &remote_net))
+ {
+ this->current = NULL;
+ return FALSE;
+ }
+ this->current = peer_cfg_create(
+ name, 2, this->ike->get_ref(this->ike),
+ CERT_NEVER_SEND, UNIQUE_REPLACE,
+ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
+ this->rekey*5, this->rekey*3, /* jitter, overtime */
+ TRUE, this->dpd, /* mobike, dpddelay */
+ NULL, NULL, /* vip, pool */
+ FALSE, NULL, NULL); /* mediation, med by, peer id */
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, me));
+ this->current->add_auth_cfg(this->current, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_encoding(ID_KEY_ID, other));
+ this->current->add_auth_cfg(this->current, auth, FALSE);
+
+ child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg->add_proposal(child_cfg, proposal_create_default(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);
+ *cfg = this->current;
+ return TRUE;
+}
+
+/**
+ * Implementation of peer_enumerator_t.public.destroy
+ */
+static void peer_enumerator_destroy(peer_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_medcli_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
+
+ e->current = NULL;
+ e->ike = this->ike;
+ e->rekey = this->rekey;
+ e->dpd = this->dpd;
+ e->public.enumerate = (void*)peer_enumerator_enumerate;
+ e->public.destroy = (void*)peer_enumerator_destroy;
+
+ /* filter on IDs: NULL or ANY or matching KEY_ID */
+ e->inner = this->db->query(this->db,
+ "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, "
+ "Connection.LocalSubnet, Connection.RemoteSubnet "
+ "FROM ClientConfig JOIN Connection "
+ "WHERE Active AND "
+ "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)",
+ DB_INT, me == NULL || me->get_type(me) == ID_ANY,
+ DB_BLOB, me && me->get_type(me) == ID_KEY_ID ?
+ me->get_encoding(me) : chunk_empty,
+ DB_INT, other == NULL || other->get_type(other) == ID_ANY,
+ DB_BLOB, other && other->get_type(other) == ID_KEY_ID ?
+ other->get_encoding(other) : chunk_empty,
+ DB_TEXT, DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * initiate a peer config
+ */
+static job_requeue_t initiate_config(peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child_cfg = NULL;;
+
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ enumerator->enumerate(enumerator, &child_cfg);
+ if (child_cfg)
+ {
+ child_cfg->get_ref(child_cfg);
+ peer_cfg->get_ref(peer_cfg);
+ enumerator->destroy(enumerator);
+ charon->controller->initiate(charon->controller,
+ peer_cfg, child_cfg, NULL, NULL);
+ }
+ else
+ {
+ enumerator->destroy(enumerator);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * schedule initation of all "active" connections
+ */
+static void schedule_autoinit(private_medcli_config_t *this)
+{
+ enumerator_t *e;
+ char *name;
+
+ e = this->db->query(this->db, "SELECT Alias FROM Connection WHERE Active",
+ DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &name))
+ {
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = get_peer_cfg_by_name(this, name);
+ if (peer_cfg)
+ {
+ /* schedule asynchronous initiation job */
+ charon->processor->queue_job(charon->processor,
+ (job_t*)callback_job_create(
+ (callback_job_cb_t)initiate_config,
+ peer_cfg, (void*)peer_cfg->destroy, NULL));
+ }
+ }
+ e->destroy(e);
+ }
+}
+
+/**
+ * Implementation of medcli_config_t.destroy.
+ */
+static void destroy(private_medcli_config_t *this)
+{
+ this->ike->destroy(this->ike);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+medcli_config_t *medcli_config_create(database_t *db)
+{
+ private_medcli_config_t *this = malloc_thing(private_medcli_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(medcli_config_t*))destroy;
+
+ this->db = db;
+ this->rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200);
+ this->dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300);
+ this->ike = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT);
+ this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+
+ schedule_autoinit(this);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/medcli/medcli_config.h b/src/libcharon/plugins/medcli/medcli_config.h
new file mode 100644
index 000000000..36c20adf7
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup medcli_config_i medcli_config
+ * @{ @ingroup medcli
+ */
+
+#ifndef MEDCLI_CONFIG_H_
+#define MEDCLI_CONFIG_H_
+
+#include <config/backend.h>
+#include <database/database.h>
+
+typedef struct medcli_config_t medcli_config_t;
+
+/**
+ * Mediation client configuration backend.
+ */
+struct medcli_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(medcli_config_t *this);
+};
+
+/**
+ * Create a medcli_config backend instance.
+ *
+ * @param db underlying database
+ * @return backend instance
+ */
+medcli_config_t *medcli_config_create(database_t *db);
+
+#endif /** MEDCLI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/medcli/medcli_creds.c b/src/libcharon/plugins/medcli/medcli_creds.c
new file mode 100644
index 000000000..9729df3f5
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_creds.c
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+
+#include "medcli_creds.h"
+
+#include <daemon.h>
+#include <library.h>
+#include <utils/enumerator.h>
+
+typedef struct private_medcli_creds_t private_medcli_creds_t;
+
+/**
+ * Private data of an medcli_creds_t object
+ */
+struct private_medcli_creds_t {
+
+ /**
+ * Public part
+ */
+ medcli_creds_t public;
+
+ /**
+ * underlying database handle
+ */
+ database_t *db;
+};
+
+/**
+ * enumerator over private keys
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated private key */
+ private_key_t *current;
+} private_enumerator_t;
+
+/**
+ * Implementation of private_enumerator_t.public.enumerate
+ */
+static bool private_enumerator_enumerate(private_enumerator_t *this,
+ private_key_t **key)
+{
+ chunk_t chunk;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &chunk))
+ {
+ this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk,
+ BUILD_END);
+ if (this->current)
+ {
+ *key = this->current;
+ return TRUE;
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of private_enumerator_t.public.destroy
+ */
+static void private_enumerator_destroy(private_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_private_enumerator.
+ */
+static enumerator_t* create_private_enumerator(private_medcli_creds_t *this,
+ key_type_t type, identification_t *id)
+{
+ private_enumerator_t *e;
+
+ if ((type != KEY_RSA && type != KEY_ANY) ||
+ id == NULL || id->get_type(id) != ID_KEY_ID)
+ {
+ DBG1(DBG_CFG, "%N - %Y", key_type_names, type, id);
+ return NULL;
+ }
+
+ e = malloc_thing(private_enumerator_t);
+ e->current = NULL;
+ e->public.enumerate = (void*)private_enumerator_enumerate;
+ e->public.destroy = (void*)private_enumerator_destroy;
+ e->inner = this->db->query(this->db,
+ "SELECT PrivateKey FROM ClientConfig WHERE KeyId = ?",
+ DB_BLOB, id->get_encoding(id),
+ DB_BLOB);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * enumerator over certificates
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated cert */
+ certificate_t *current;
+ /** type of requested key */
+ key_type_t type;
+} cert_enumerator_t;
+
+/**
+ * Implementation of cert_enumerator_t.public.enumerate
+ */
+static bool cert_enumerator_enumerate(cert_enumerator_t *this,
+ certificate_t **cert)
+{
+ public_key_t *public;
+ chunk_t chunk;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &chunk))
+ {
+ public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ BUILD_BLOB_ASN1_DER, chunk,
+ BUILD_END);
+ if (public)
+ {
+ if (this->type == KEY_ANY || this->type == public->get_type(public))
+ {
+ this->current = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, public, BUILD_END);
+ public->destroy(public);
+ if (this->current)
+ {
+ *cert = this->current;
+ return TRUE;
+ }
+ }
+ else
+ {
+ public->destroy(public);
+ }
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of cert_enumerator_t.public.destroy
+ */
+static void cert_enumerator_destroy(cert_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_cert_enumerator.
+ */
+static enumerator_t* create_cert_enumerator(private_medcli_creds_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_enumerator_t *e;
+
+ if ((cert != CERT_TRUSTED_PUBKEY && cert != CERT_ANY) ||
+ id == NULL || id->get_type(id) != ID_KEY_ID)
+ {
+ return NULL;
+ }
+
+ e = malloc_thing(cert_enumerator_t);
+ e->current = NULL;
+ e->type = key;
+ e->public.enumerate = (void*)cert_enumerator_enumerate;
+ e->public.destroy = (void*)cert_enumerator_destroy;
+ e->inner = this->db->query(this->db,
+ "SELECT PublicKey FROM ClientConfig WHERE KeyId = ? UNION "
+ "SELECT PublicKey FROM MediationServerConfig WHERE KeyId = ? UNION "
+ "SELECT PublicKey FROM Connection WHERE KeyId = ?",
+ DB_BLOB, id->get_encoding(id),
+ DB_BLOB, id->get_encoding(id),
+ DB_BLOB, id->get_encoding(id),
+ DB_BLOB);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of backend_t.destroy.
+ */
+static void destroy(private_medcli_creds_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+medcli_creds_t *medcli_creds_create(database_t *db)
+{
+ private_medcli_creds_t *this = malloc_thing(private_medcli_creds_t);
+
+ this->public.set.create_private_enumerator = (void*)create_private_enumerator;
+ this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+
+ this->public.destroy = (void (*)(medcli_creds_t*))destroy;
+
+ this->db = db;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/medcli/medcli_creds.h b/src/libcharon/plugins/medcli/medcli_creds.h
new file mode 100644
index 000000000..4b5402653
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_creds.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup medcli_creds_i medcli_creds
+ * @{ @ingroup medcli
+ */
+
+#ifndef MEDCLI_CREDS_H_
+#define MEDCLI_CREDS_H_
+
+#include <credentials/credential_set.h>
+#include <database/database.h>
+
+typedef struct medcli_creds_t medcli_creds_t;
+
+/**
+ * Mediation client credentials database.
+ */
+struct medcli_creds_t {
+
+ /**
+ * Implements credential_set_t interface
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy the credentials databse.
+ */
+ void (*destroy)(medcli_creds_t *this);
+};
+
+/**
+ * Create the medcli credential set.
+ *
+ * @param database underlying database
+ * @return credential set implementation on that database
+ */
+medcli_creds_t *medcli_creds_create(database_t *database);
+
+#endif /** MEDCLI_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/medcli/medcli_listener.c b/src/libcharon/plugins/medcli/medcli_listener.c
new file mode 100644
index 000000000..142f02e6c
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_listener.c
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#include "medcli_listener.h"
+
+#include <daemon.h>
+#include <library.h>
+
+typedef struct private_medcli_listener_t private_medcli_listener_t;
+typedef enum mediated_state_t mediated_state_t;
+
+/**
+ * state of a mediated connection
+ */
+enum mediated_state_t {
+ STATE_DOWN = 1,
+ STATE_CONNECTING = 2,
+ STATE_UP = 3,
+};
+
+/**
+ * Private data of an medcli_listener_t object
+ */
+struct private_medcli_listener_t {
+
+ /**
+ * Public part
+ */
+ medcli_listener_t public;
+
+ /**
+ * underlying database handle
+ */
+ database_t *db;
+};
+
+/**
+ * Implementation of bus_listener_t.signal.
+ */
+static void set_state(private_medcli_listener_t *this, char *alias,
+ mediated_state_t state)
+{
+ this->db->execute(this->db, NULL,
+ "UPDATE Connection SET Status = ? WHERE Alias = ?",
+ DB_UINT, state, DB_TEXT, alias);
+}
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(private_medcli_listener_t *this,
+ ike_sa_t *ike_sa, ike_sa_state_t state)
+{
+ if (ike_sa)
+ {
+ switch (state)
+ {
+ case IKE_CONNECTING:
+ set_state(this, ike_sa->get_name(ike_sa), STATE_CONNECTING);
+ break;
+ case IKE_DESTROYING:
+ set_state(this, ike_sa->get_name(ike_sa), STATE_DOWN);
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(private_medcli_listener_t *this,
+ ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (ike_sa && child_sa)
+ {
+ switch (state)
+ {
+ case CHILD_INSTALLED:
+ set_state(this, child_sa->get_name(child_sa), STATE_UP);
+ break;
+ case CHILD_DESTROYING:
+ set_state(this, child_sa->get_name(child_sa), STATE_DOWN);
+ break;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of backend_t.destroy.
+ */
+static void destroy(private_medcli_listener_t *this)
+{
+ this->db->execute(this->db, NULL, "UPDATE Connection SET Status = ?",
+ DB_UINT, STATE_DOWN);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+medcli_listener_t *medcli_listener_create(database_t *db)
+{
+ private_medcli_listener_t *this = malloc_thing(private_medcli_listener_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+
+ this->public.listener.ike_state_change = (void*)ike_state_change;
+ this->public.listener.child_state_change = (void*)child_state_change;
+ this->public.destroy = (void (*)(medcli_listener_t*))destroy;
+
+ this->db = db;
+ db->execute(db, NULL, "UPDATE Connection SET Status = ?",
+ DB_UINT, STATE_DOWN);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/medcli/medcli_listener.h b/src/libcharon/plugins/medcli/medcli_listener.h
new file mode 100644
index 000000000..4768beccd
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_listener.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup medcli_listener_i medcli_listener
+ * @{ @ingroup medcli
+ */
+
+#ifndef MEDCLI_LISTENER_H_
+#define MEDCLI_LISTENER_H_
+
+#include <bus/bus.h>
+#include <database/database.h>
+
+typedef struct medcli_listener_t medcli_listener_t;
+
+/**
+ * Mediation client listener, writes connection status to database
+ */
+struct medcli_listener_t {
+
+ /**
+ * Implements bus_listener_t interface
+ */
+ listener_t listener;
+
+ /**
+ * Destroy the credentials databse.
+ */
+ void (*destroy)(medcli_listener_t *this);
+};
+
+/**
+ * Create the medcli credential set.
+ *
+ * @param database underlying database
+ * @return listener
+ */
+medcli_listener_t *medcli_listener_create(database_t *database);
+
+#endif /** MEDCLI_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/medcli/medcli_plugin.c b/src/libcharon/plugins/medcli/medcli_plugin.c
new file mode 100644
index 000000000..397168d46
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_plugin.c
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#include "medcli_plugin.h"
+
+#include "medcli_creds.h"
+#include "medcli_config.h"
+#include "medcli_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_medcli_plugin_t private_medcli_plugin_t;
+
+/**
+ * private data of medcli plugin
+ */
+struct private_medcli_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ medcli_plugin_t public;
+
+ /**
+ * database connection instance
+ */
+ database_t *db;
+
+ /**
+ * medcli credential set instance
+ */
+ medcli_creds_t *creds;
+
+ /**
+ * medcli config database
+ */
+ medcli_config_t *config;
+
+ /**
+ * Listener to update database connection state
+ */
+ medcli_listener_t *listener;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_medcli_plugin_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ this->listener->destroy(this->listener);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *medcli_plugin_create()
+{
+ char *uri;
+ private_medcli_plugin_t *this = malloc_thing(private_medcli_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ uri = lib->settings->get_str(lib->settings,
+ "medcli.database", NULL);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "mediation client database URI not defined, skipped");
+ free(this);
+ return NULL;
+ }
+
+ this->db = lib->db->create(lib->db, uri);
+ if (this->db == NULL)
+ {
+ DBG1(DBG_CFG, "opening mediation client database failed");
+ free(this);
+ return NULL;
+ }
+
+ this->creds = medcli_creds_create(this->db);
+ this->config = medcli_config_create(this->db);
+ this->listener = medcli_listener_create(this->db);
+
+ charon->credentials->add_set(charon->credentials, &this->creds->set);
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/medcli/medcli_plugin.h b/src/libcharon/plugins/medcli/medcli_plugin.h
new file mode 100644
index 000000000..44e7bb525
--- /dev/null
+++ b/src/libcharon/plugins/medcli/medcli_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 medcli medcli
+ * @ingroup cplugins
+ *
+ * @defgroup medcli_plugin medcli_plugin
+ * @{ @ingroup medcli
+ */
+
+#ifndef MEDCLI_PLUGIN_H_
+#define MEDCLI_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct medcli_plugin_t medcli_plugin_t;
+
+/**
+ * Mediation client database plugin.
+ */
+struct medcli_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** MEDCLI_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/medsrv/Makefile.am b/src/libcharon/plugins/medsrv/Makefile.am
new file mode 100644
index 000000000..7f5c8e2b3
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-medsrv.la
+else
+plugin_LTLIBRARIES = libstrongswan-medsrv.la
+endif
+
+libstrongswan_medsrv_la_SOURCES = \
+ medsrv_plugin.h medsrv_plugin.c \
+ medsrv_creds.h medsrv_creds.c \
+ medsrv_config.h medsrv_config.c
+
+libstrongswan_medsrv_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
new file mode 100644
index 000000000..a103a1340
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -0,0 +1,591 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/medsrv
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_medsrv_la_LIBADD =
+am_libstrongswan_medsrv_la_OBJECTS = medsrv_plugin.lo medsrv_creds.lo \
+ medsrv_config.lo
+libstrongswan_medsrv_la_OBJECTS = \
+ $(am_libstrongswan_medsrv_la_OBJECTS)
+libstrongswan_medsrv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_medsrv_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_medsrv_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_medsrv_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_medsrv_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_medsrv_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-medsrv.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-medsrv.la
+libstrongswan_medsrv_la_SOURCES = \
+ medsrv_plugin.h medsrv_plugin.c \
+ medsrv_creds.h medsrv_creds.c \
+ medsrv_config.h medsrv_config.c
+
+libstrongswan_medsrv_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/medsrv/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/medsrv/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-medsrv.la: $(libstrongswan_medsrv_la_OBJECTS) $(libstrongswan_medsrv_la_DEPENDENCIES)
+ $(libstrongswan_medsrv_la_LINK) $(am_libstrongswan_medsrv_la_rpath) $(libstrongswan_medsrv_la_OBJECTS) $(libstrongswan_medsrv_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
new file mode 100644
index 000000000..c23955ad0
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+
+#include "medsrv_config.h"
+
+#include <daemon.h>
+
+typedef struct private_medsrv_config_t private_medsrv_config_t;
+
+/**
+ * Private data of an medsrv_config_t object
+ */
+struct private_medsrv_config_t {
+
+ /**
+ * Public part
+ */
+ medsrv_config_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+
+ /**
+ * rekey time
+ */
+ int rekey;
+
+ /**
+ * dpd delay
+ */
+ int dpd;
+
+ /**
+ * default ike config
+ */
+ ike_cfg_t *ike;
+};
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_medsrv_config_t *this, char *name)
+{
+ return NULL;
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_medsrv_config_t *this,
+ host_t *me, host_t *other)
+{
+ return enumerator_create_single(this->ike, NULL);
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ enumerator_t *e;
+
+ if (!me || !other || other->get_type(other) != ID_KEY_ID)
+ {
+ return NULL;
+ }
+ e = this->db->query(this->db,
+ "SELECT CONCAT(peer.alias, CONCAT('@', user.login)) FROM "
+ "peer JOIN user ON peer.user = user.id "
+ "WHERE peer.keyid = ?", DB_BLOB, other->get_encoding(other),
+ DB_TEXT);
+ if (e)
+ {
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth;
+ char *name;
+
+ if (e->enumerate(e, &name))
+ {
+ peer_cfg = peer_cfg_create(
+ name, 2, this->ike->get_ref(this->ike),
+ CERT_NEVER_SEND, UNIQUE_REPLACE,
+ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
+ this->rekey*5, this->rekey*3, /* jitter, overtime */
+ TRUE, this->dpd, /* mobike, dpddelay */
+ NULL, NULL, /* vip, pool */
+ TRUE, NULL, NULL); /* mediation, med by, peer id */
+ e->destroy(e);
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY, me->clone(me));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY, other->clone(other));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
+ return enumerator_create_single(peer_cfg, (void*)peer_cfg->destroy);
+ }
+ e->destroy(e);
+ }
+ return NULL;
+}
+
+/**
+ * Implementation of medsrv_config_t.destroy.
+ */
+static void destroy(private_medsrv_config_t *this)
+{
+ this->ike->destroy(this->ike);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+medsrv_config_t *medsrv_config_create(database_t *db)
+{
+ private_medsrv_config_t *this = malloc_thing(private_medsrv_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(medsrv_config_t*))destroy;
+
+ this->db = db;
+ this->rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200);
+ this->dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300);
+ this->ike = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT);
+ this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.h b/src/libcharon/plugins/medsrv/medsrv_config.h
new file mode 100644
index 000000000..fc8b0e972
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup medsrv_config_i medsrv_config
+ * @{ @ingroup medsrv
+ */
+
+#ifndef MEDSRV_CONFIG_H_
+#define MEDSRV_CONFIG_H_
+
+#include <config/backend.h>
+#include <database/database.h>
+
+typedef struct medsrv_config_t medsrv_config_t;
+
+/**
+ * Mediation server configuration backend.
+ */
+struct medsrv_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(medsrv_config_t *this);
+};
+
+/**
+ * Create a medsrv_config backend instance.
+ *
+ * @param db underlying database
+ * @return backend instance
+ */
+medsrv_config_t *medsrv_config_create(database_t *db);
+
+#endif /** MEDSRV_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.c b/src/libcharon/plugins/medsrv/medsrv_creds.c
new file mode 100644
index 000000000..8d1643908
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_creds.c
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#include "medsrv_creds.h"
+
+#include <daemon.h>
+#include <library.h>
+#include <utils/enumerator.h>
+
+typedef struct private_medsrv_creds_t private_medsrv_creds_t;
+
+/**
+ * Private data of an medsrv_creds_t object
+ */
+struct private_medsrv_creds_t {
+
+ /**
+ * Public part
+ */
+ medsrv_creds_t public;
+
+ /**
+ * underlying database handle
+ */
+ database_t *db;
+};
+
+/**
+ * enumerator over certificates
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated cert */
+ certificate_t *current;
+ /** type of requested key */
+ key_type_t type;
+} cert_enumerator_t;
+
+/**
+ * Implementation of cert_enumerator_t.public.enumerate
+ */
+static bool cert_enumerator_enumerate(cert_enumerator_t *this,
+ certificate_t **cert)
+{
+ certificate_t *trusted;
+ public_key_t *public;
+ chunk_t chunk;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &chunk))
+ {
+ public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ BUILD_BLOB_ASN1_DER, chunk,
+ BUILD_END);
+ if (public)
+ {
+ if (this->type == KEY_ANY || this->type == public->get_type(public))
+ {
+ trusted = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, public, BUILD_END);
+ public->destroy(public);
+ if (trusted)
+ {
+ *cert = this->current = trusted;
+ return TRUE;
+ }
+ }
+ else
+ {
+ public->destroy(public);
+ }
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of cert_enumerator_t.public.destroy
+ */
+static void cert_enumerator_destroy(cert_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_cert_enumerator.
+ */
+static enumerator_t* create_cert_enumerator(private_medsrv_creds_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_enumerator_t *e;
+
+ if ((cert != CERT_TRUSTED_PUBKEY && cert != CERT_ANY) ||
+ id == NULL || id->get_type(id) != ID_KEY_ID)
+ {
+ return NULL;
+ }
+
+ e = malloc_thing(cert_enumerator_t);
+ e->current = NULL;
+ e->type = key;
+ e->public.enumerate = (void*)cert_enumerator_enumerate;
+ e->public.destroy = (void*)cert_enumerator_destroy;
+ e->inner = this->db->query(this->db,
+ "SELECT public_key FROM peer WHERE keyid = ?",
+ DB_BLOB, id->get_encoding(id),
+ DB_BLOB);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of backend_t.destroy.
+ */
+static void destroy(private_medsrv_creds_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+medsrv_creds_t *medsrv_creds_create(database_t *db)
+{
+ private_medsrv_creds_t *this = malloc_thing(private_medsrv_creds_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+
+ this->public.destroy = (void (*)(medsrv_creds_t*))destroy;
+
+ this->db = db;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.h b/src/libcharon/plugins/medsrv/medsrv_creds.h
new file mode 100644
index 000000000..d08adf3bf
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_creds.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007-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 medsrv_creds_i medsrv_creds
+ * @{ @ingroup medsrv
+ */
+
+#ifndef MEDSRV_CREDS_H_
+#define MEDSRV_CREDS_H_
+
+#include <credentials/credential_set.h>
+#include <database/database.h>
+
+typedef struct medsrv_creds_t medsrv_creds_t;
+
+/**
+ * Mediation credentials database.
+ */
+struct medsrv_creds_t {
+
+ /**
+ * Implements credential_set_t interface
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy the credentials databse.
+ */
+ void (*destroy)(medsrv_creds_t *this);
+};
+
+/**
+ * Create the medsrv credentials db.
+ *
+ * @param database underlying database
+ * @return credential set implementation on that database
+ */
+medsrv_creds_t *medsrv_creds_create(database_t *database);
+
+#endif /** MEDSRV_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.c b/src/libcharon/plugins/medsrv/medsrv_plugin.c
new file mode 100644
index 000000000..262d26d6b
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_plugin.c
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include "medsrv_plugin.h"
+
+#include "medsrv_creds.h"
+#include "medsrv_config.h"
+
+#include <daemon.h>
+
+typedef struct private_medsrv_plugin_t private_medsrv_plugin_t;
+
+/**
+ * private data of medsrv plugin
+ */
+struct private_medsrv_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ medsrv_plugin_t public;
+
+ /**
+ * database connection instance
+ */
+ database_t *db;
+
+ /**
+ * medsrv credential set instance
+ */
+ medsrv_creds_t *creds;
+
+ /**
+ * medsrv config database
+ */
+ medsrv_config_t *config;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_medsrv_plugin_t *this)
+{
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *medsrv_plugin_create()
+{
+ char *uri;
+ private_medsrv_plugin_t *this = malloc_thing(private_medsrv_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ uri = lib->settings->get_str(lib->settings,
+ "medsrv.database", NULL);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "mediation database URI not defined, skipped");
+ free(this);
+ return NULL;
+ }
+
+ this->db = lib->db->create(lib->db, uri);
+ if (this->db == NULL)
+ {
+ DBG1(DBG_CFG, "opening mediation server database failed");
+ free(this);
+ return NULL;
+ }
+
+ this->creds = medsrv_creds_create(this->db);
+ this->config = medsrv_config_create(this->db);
+
+ charon->credentials->add_set(charon->credentials, &this->creds->set);
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.h b/src/libcharon/plugins/medsrv/medsrv_plugin.h
new file mode 100644
index 000000000..8736822ee
--- /dev/null
+++ b/src/libcharon/plugins/medsrv/medsrv_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 medsrv medsrv
+ * @ingroup cplugins
+ *
+ * @defgroup medsrv_plugin medsrv_plugin
+ * @{ @ingroup medsrv
+ */
+
+#ifndef MEDSRV_PLUGIN_H_
+#define MEDSRV_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct medsrv_plugin_t medsrv_plugin_t;
+
+/**
+ * Mediation server database plugin.
+ */
+struct medsrv_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** MEDSRV_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/nm/Makefile.am b/src/libcharon/plugins/nm/Makefile.am
new file mode 100644
index 000000000..8e12a72be
--- /dev/null
+++ b/src/libcharon/plugins/nm/Makefile.am
@@ -0,0 +1,21 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon ${nm_CFLAGS}
+
+AM_CFLAGS = -rdynamic \
+ -DNM_CA_DIR=\"${nm_ca_dir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-nm.la
+else
+plugin_LTLIBRARIES = libstrongswan-nm.la
+endif
+
+libstrongswan_nm_la_SOURCES = \
+ nm_plugin.h nm_plugin.c \
+ nm_service.h nm_service.c \
+ nm_creds.h nm_creds.c \
+ nm_handler.h nm_handler.c
+
+libstrongswan_nm_la_LDFLAGS = -module -avoid-version
+libstrongswan_nm_la_LIBADD = ${nm_LIBS}
diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in
new file mode 100644
index 000000000..c7f288f54
--- /dev/null
+++ b/src/libcharon/plugins/nm/Makefile.in
@@ -0,0 +1,595 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/nm
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libstrongswan_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libstrongswan_nm_la_OBJECTS = nm_plugin.lo nm_service.lo \
+ nm_creds.lo nm_handler.lo
+libstrongswan_nm_la_OBJECTS = $(am_libstrongswan_nm_la_OBJECTS)
+libstrongswan_nm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_nm_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_nm_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_nm_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_nm_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_nm_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon ${nm_CFLAGS}
+
+AM_CFLAGS = -rdynamic \
+ -DNM_CA_DIR=\"${nm_ca_dir}\"
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-nm.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-nm.la
+libstrongswan_nm_la_SOURCES = \
+ nm_plugin.h nm_plugin.c \
+ nm_service.h nm_service.c \
+ nm_creds.h nm_creds.c \
+ nm_handler.h nm_handler.c
+
+libstrongswan_nm_la_LDFLAGS = -module -avoid-version
+libstrongswan_nm_la_LIBADD = ${nm_LIBS}
+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/nm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/nm/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-nm.la: $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_DEPENDENCIES)
+ $(libstrongswan_nm_la_LINK) $(am_libstrongswan_nm_la_rpath) $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_service.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c
new file mode 100644
index 000000000..193838e6b
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_creds.c
@@ -0,0 +1,447 @@
+/*
+ * 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.
+ */
+
+#include "nm_creds.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_nm_creds_t private_nm_creds_t;
+
+/**
+ * private data of nm_creds
+ */
+struct private_nm_creds_t {
+
+ /**
+ * public functions
+ */
+ nm_creds_t public;
+
+ /**
+ * List of trusted certificates, certificate_t*
+ */
+ linked_list_t *certs;
+
+ /**
+ * User name
+ */
+ identification_t *user;
+
+ /**
+ * User password
+ */
+ char *pass;
+
+ /**
+ * users certificate
+ */
+ certificate_t *usercert;
+
+ /**
+ * users private key
+ */
+ private_key_t *key;
+
+ /**
+ * read/write lock
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Enumerator for user certificate
+ */
+static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
+ certificate_type_t cert, key_type_t key)
+{
+ public_key_t *public;
+
+ if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert))
+ {
+ return NULL;
+ }
+ if (key != KEY_ANY)
+ {
+ public = this->usercert->get_public_key(this->usercert);
+ if (!public)
+ {
+ return NULL;
+ }
+ if (public->get_type(public) != key)
+ {
+ public->destroy(public);
+ return NULL;
+ }
+ public->destroy(public);
+ }
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(
+ enumerator_create_single(this->usercert, NULL),
+ (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * CA certificate enumerator data
+ */
+typedef struct {
+ /** ref to credential credential store */
+ private_nm_creds_t *this;
+ /** type of key we are looking for */
+ key_type_t key;
+ /** CA certificate ID */
+ identification_t *id;
+} cert_data_t;
+
+/**
+ * Destroy CA certificate enumerator data
+ */
+static void cert_data_destroy(cert_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * Filter function for certificates enumerator
+ */
+static bool cert_filter(cert_data_t *data, certificate_t **in,
+ certificate_t **out)
+{
+ certificate_t *cert = *in;
+ public_key_t *public;
+
+ public = cert->get_public_key(cert);
+ if (!public)
+ {
+ return FALSE;
+ }
+ if (data->key != KEY_ANY && public->get_type(public) != data->key)
+ {
+ public->destroy(public);
+ return FALSE;
+ }
+ if (data->id && data->id->get_type(data->id) == ID_KEY_ID &&
+ public->has_fingerprint(public, data->id->get_encoding(data->id)))
+ {
+ public->destroy(public);
+ *out = cert;
+ return TRUE;
+ }
+ public->destroy(public);
+ if (data->id && !cert->has_subject(cert, data->id))
+ {
+ return FALSE;
+ }
+ *out = cert;
+ return TRUE;
+}
+
+/**
+ * Create enumerator for trusted certificates
+ */
+static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this,
+ key_type_t key, identification_t *id)
+{
+ cert_data_t *data = malloc_thing(cert_data_t);
+
+ data->this = this;
+ data->id = id;
+ data->key = key;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(
+ this->certs->create_enumerator(this->certs),
+ (void*)cert_filter, data, (void*)cert_data_destroy);
+}
+
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ if (id && this->usercert &&
+ id->equals(id, this->usercert->get_subject(this->usercert)))
+ {
+ return create_usercert_enumerator(this, cert, key);
+ }
+ if (cert == CERT_X509 || cert == CERT_ANY)
+ {
+ return create_trusted_cert_enumerator(this, key, id);
+ }
+ return NULL;
+}
+
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_private_enumerator(private_nm_creds_t *this,
+ key_type_t type, identification_t *id)
+{
+ if (this->key == NULL)
+ {
+ return NULL;
+ }
+ if (type != KEY_ANY && type != this->key->get_type(this->key))
+ {
+ return NULL;
+ }
+ if (id && id->get_type(id) != ID_ANY)
+ {
+ if (id->get_type(id) != ID_KEY_ID ||
+ !this->key->has_fingerprint(this->key, id->get_encoding(id)))
+ {
+ return NULL;
+ }
+ }
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
+ (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * shared key enumerator implementation
+ */
+typedef struct {
+ enumerator_t public;
+ private_nm_creds_t *this;
+ shared_key_t *key;
+ bool done;
+} shared_enumerator_t;
+
+/**
+ * enumerate function for shared enumerator
+ */
+static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
+ id_match_t *me, id_match_t *other)
+{
+ if (this->done)
+ {
+ return FALSE;
+ }
+ *key = this->key;
+ *me = ID_MATCH_PERFECT;
+ *other = ID_MATCH_ANY;
+ this->done = TRUE;
+ return TRUE;
+}
+
+/**
+ * Destroy function for shared enumerator
+ */
+static void shared_destroy(shared_enumerator_t *this)
+{
+ this->key->destroy(this->key);
+ this->this->lock->unlock(this->this->lock);
+ free(this);
+}
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
+ shared_key_type_t type, identification_t *me,
+ identification_t *other)
+{
+ shared_enumerator_t *enumerator;
+
+ if (!this->pass || !this->user)
+ {
+ return NULL;
+ }
+ if (type != SHARED_EAP && type != SHARED_IKE)
+ {
+ return NULL;
+ }
+ if (me && !me->equals(me, this->user))
+ {
+ return NULL;
+ }
+
+ enumerator = malloc_thing(shared_enumerator_t);
+ enumerator->public.enumerate = (void*)shared_enumerate;
+ enumerator->public.destroy = (void*)shared_destroy;
+ enumerator->this = this;
+ enumerator->done = FALSE;
+ this->lock->read_lock(this->lock);
+ enumerator->key = shared_key_create(type,
+ chunk_clone(chunk_create(this->pass,
+ strlen(this->pass))));
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of nm_creds_t.add_certificate
+ */
+static void add_certificate(private_nm_creds_t *this, certificate_t *cert)
+{
+ this->lock->write_lock(this->lock);
+ this->certs->insert_last(this->certs, cert);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Load a certificate file
+ */
+static void load_ca_file(private_nm_creds_t *this, char *file)
+{
+ certificate_t *cert;
+
+ /* We add the CA constraint, as many CAs miss it */
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file, BUILD_END);
+ if (!cert)
+ {
+ DBG1(DBG_CFG, "loading CA certificate '%s' failed", file);
+ }
+ else
+ {
+ DBG2(DBG_CFG, "loaded CA certificate '%Y'", cert->get_subject(cert));
+ x509_t *x509 = (x509_t*)cert;
+ if (!(x509->get_flags(x509) & X509_SELF_SIGNED))
+ {
+ DBG1(DBG_CFG, "%Y is not self signed", cert->get_subject(cert));
+ }
+ this->certs->insert_last(this->certs, cert);
+ }
+}
+
+/**
+ * Implementation of nm_creds_t.load_ca_dir
+ */
+static void load_ca_dir(private_nm_creds_t *this, char *dir)
+{
+ enumerator_t *enumerator;
+ char *rel, *abs;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(dir);
+ if (enumerator)
+ {
+ while (enumerator->enumerate(enumerator, &rel, &abs, &st))
+ {
+ /* skip '.', '..' and hidden files */
+ if (rel[0] != '.')
+ {
+ if (S_ISDIR(st.st_mode))
+ {
+ load_ca_dir(this, abs);
+ }
+ else if (S_ISREG(st.st_mode))
+ {
+ load_ca_file(this, abs);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+/**
+ * Implementation of nm_creds_t.set_password
+ */
+static void set_username_password(private_nm_creds_t *this, identification_t *id,
+ char *password)
+{
+ this->lock->write_lock(this->lock);
+ DESTROY_IF(this->user);
+ this->user = id->clone(id);
+ free(this->pass);
+ this->pass = password ? strdup(password) : NULL;
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of nm_creds_t.set_cert_and_key
+ */
+static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
+ private_key_t *key)
+{
+ this->lock->write_lock(this->lock);
+ DESTROY_IF(this->key);
+ DESTROY_IF(this->usercert);
+ this->key = key;
+ this->usercert = cert;
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of nm_creds_t.clear
+ */
+static void clear(private_nm_creds_t *this)
+{
+ certificate_t *cert;
+
+ while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
+ {
+ cert->destroy(cert);
+ }
+ DESTROY_IF(this->user);
+ free(this->pass);
+ DESTROY_IF(this->usercert);
+ DESTROY_IF(this->key);
+ this->key = NULL;
+ this->usercert = NULL;
+ this->pass = NULL;
+ this->user = NULL;
+}
+
+/**
+ * Implementation of nm_creds_t.destroy
+ */
+static void destroy(private_nm_creds_t *this)
+{
+ clear(this);
+ this->certs->destroy(this->certs);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+nm_creds_t *nm_creds_create()
+{
+ private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
+
+ this->public.set.create_private_enumerator = (void*)create_private_enumerator;
+ this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
+ this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.add_certificate = (void(*)(nm_creds_t*, certificate_t *cert))add_certificate;
+ this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir;
+ this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password;
+ this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key;
+ this->public.clear = (void(*)(nm_creds_t*))clear;
+ this->public.destroy = (void(*)(nm_creds_t*))destroy;
+
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ this->certs = linked_list_create();
+ this->user = NULL;
+ this->pass = NULL;
+ this->usercert = NULL;
+ this->key = NULL;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h
new file mode 100644
index 000000000..b55cff31e
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_creds.h
@@ -0,0 +1,85 @@
+/*
+ * 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 nm_creds nm_creds
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_CREDS_H_
+#define NM_CREDS_H_
+
+#include <credentials/keys/private_key.h>
+#include <credentials/credential_set.h>
+
+typedef struct nm_creds_t nm_creds_t;
+
+/**
+ * NetworkManager credentials helper.
+ */
+struct nm_creds_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Add a trusted gateway certificate to serve by this set.
+ *
+ * @param cert certificate to serve
+ */
+ void (*add_certificate)(nm_creds_t *this, certificate_t *cert);
+
+ /**
+ * Load CA certificates recursively from a directory.
+ *
+ * @param dir directory to PEM encoded CA certificates
+ */
+ void (*load_ca_dir)(nm_creds_t *this, char *dir);
+
+ /**
+ * Set the username/password for authentication.
+ *
+ * @param id ID of the user
+ * @param password password to use for authentication
+ */
+ void (*set_username_password)(nm_creds_t *this, identification_t *id,
+ char *password);
+ /**
+ * Set the certificate and private key to use for client authentication.
+ *
+ * @param cert client certificate
+ * @param key associated private key
+ */
+ void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
+ private_key_t *key);
+ /**
+ * Clear the stored credentials.
+ */
+ void (*clear)(nm_creds_t *this);
+
+ /**
+ * Destroy a nm_creds instance.
+ */
+ void (*destroy)(nm_creds_t *this);
+};
+
+/**
+ * Create a nm_creds instance.
+ */
+nm_creds_t *nm_creds_create();
+
+#endif /** NM_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c
new file mode 100644
index 000000000..eacb54dda
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_handler.c
@@ -0,0 +1,193 @@
+/*
+ * 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 "nm_handler.h"
+
+#include <daemon.h>
+
+typedef struct private_nm_handler_t private_nm_handler_t;
+
+/**
+ * Private data of an nm_handler_t object.
+ */
+struct private_nm_handler_t {
+
+ /**
+ * Public nm_handler_t interface.
+ */
+ nm_handler_t public;
+
+ /**
+ * list of received DNS server attributes, pointer to 4 byte data
+ */
+ linked_list_t *dns;
+
+ /**
+ * list of received NBNS server attributes, pointer to 4 byte data
+ */
+ linked_list_t *nbns;
+};
+
+/**
+ * Implementation of attribute_handler_t.handle
+ */
+static bool handle(private_nm_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ linked_list_t *list;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ list = this->dns;
+ break;
+ case INTERNAL_IP4_NBNS:
+ list = this->nbns;
+ break;
+ default:
+ return FALSE;
+ }
+ if (data.len != 4)
+ {
+ return FALSE;
+ }
+ list->insert_last(list, chunk_clone(data).ptr);
+ return TRUE;
+}
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate() for WINS
+ */
+static bool enumerate_nbns(enumerator_t *this,
+ configuration_attribute_type_t *type, chunk_t *data)
+{
+ *type = INTERNAL_IP4_NBNS;
+ *data = chunk_empty;
+ /* done */
+ this->enumerate = (void*)return_false;
+ return TRUE;
+}
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate() for DNS
+ */
+static bool enumerate_dns(enumerator_t *this,
+ configuration_attribute_type_t *type, chunk_t *data)
+{
+ *type = INTERNAL_IP4_DNS;
+ *data = chunk_empty;
+ /* enumerate WINS server as next attribute ... */
+ this->enumerate = (void*)enumerate_nbns;
+ return TRUE;
+}
+
+/**
+ * Implementation of attribute_handler_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this,
+ identification_t *server, host_t *vip)
+{
+ if (vip && vip->get_family(vip) == AF_INET)
+ { /* no IPv6 attributes yet */
+ enumerator_t *enumerator = malloc_thing(enumerator_t);
+ /* enumerate DNS attribute first ... */
+ enumerator->enumerate = (void*)enumerate_dns;
+ enumerator->destroy = (void*)free;
+
+ return enumerator;
+ }
+ return enumerator_create_empty();
+}
+
+/**
+ * convert plain byte ptrs to handy chunk during enumeration
+ */
+static bool filter_chunks(void* null, char **in, chunk_t *out)
+{
+ *out = chunk_create(*in, 4);
+ return TRUE;
+}
+
+/**
+ * Implementation of nm_handler_t.create_enumerator
+ */
+static enumerator_t* create_enumerator(private_nm_handler_t *this,
+ configuration_attribute_type_t type)
+{
+ linked_list_t *list;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ list = this->dns;
+ break;
+ case INTERNAL_IP4_NBNS:
+ list = this->nbns;
+ break;
+ default:
+ return enumerator_create_empty();
+ }
+ return enumerator_create_filter(list->create_enumerator(list),
+ (void*)filter_chunks, NULL, NULL);
+}
+
+/**
+ * Implementation of nm_handler_t.reset
+ */
+static void reset(private_nm_handler_t *this)
+{
+ void *data;
+
+ while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS)
+ {
+ free(data);
+ }
+ while (this->nbns->remove_last(this->nbns, (void**)&data) == SUCCESS)
+ {
+ free(data);
+ }
+}
+
+/**
+ * Implementation of nm_handler_t.destroy.
+ */
+static void destroy(private_nm_handler_t *this)
+{
+ reset(this);
+ this->dns->destroy(this->dns);
+ this->nbns->destroy(this->nbns);
+ free(this);
+}
+
+/**
+ * See header
+ */
+nm_handler_t *nm_handler_create()
+{
+ private_nm_handler_t *this = malloc_thing(private_nm_handler_t);
+
+ this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
+ this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop;
+ this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
+ this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator;
+ this->public.reset = (void(*)(nm_handler_t*))reset;
+ this->public.destroy = (void(*)(nm_handler_t*))destroy;
+
+ this->dns = linked_list_create();
+ this->nbns = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/nm/nm_handler.h b/src/libcharon/plugins/nm/nm_handler.h
new file mode 100644
index 000000000..bb35ce767
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_handler.h
@@ -0,0 +1,62 @@
+/*
+ * 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 nm_handler nm_handler
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_HANDLER_H_
+#define NM_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct nm_handler_t nm_handler_t;
+
+/**
+ * Handles DNS/NBNS attributes to pass to NM.
+ */
+struct nm_handler_t {
+
+ /**
+ * Implements attribute handler interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Create an enumerator over received attributes of a given kind.
+ *
+ * @param type type of attributes to enumerate
+ * @return enumerator over attribute data (chunk_t)
+ */
+ enumerator_t* (*create_enumerator)(nm_handler_t *this,
+ configuration_attribute_type_t type);
+ /**
+ * Reset state, flush all received attributes.
+ */
+ void (*reset)(nm_handler_t *this);
+
+ /**
+ * Destroy a nm_handler_t.
+ */
+ void (*destroy)(nm_handler_t *this);
+};
+
+/**
+ * Create a nm_handler instance.
+ */
+nm_handler_t *nm_handler_create();
+
+#endif /** NM_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c
new file mode 100644
index 000000000..6087f6589
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_plugin.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008-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 "nm_plugin.h"
+#include "nm_service.h"
+#include "nm_creds.h"
+#include "nm_handler.h"
+
+#include <hydra.h>
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+#define CAP_DAC_OVERRIDE 1
+
+typedef struct private_nm_plugin_t private_nm_plugin_t;
+
+/**
+ * private data of nm plugin
+ */
+struct private_nm_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ nm_plugin_t public;
+
+ /**
+ * NetworkManager service (VPNPlugin)
+ */
+ NMStrongswanPlugin *plugin;
+
+ /**
+ * Glib main loop for a thread, handles DBUS calls
+ */
+ GMainLoop *loop;
+
+ /**
+ * credential set registered at the daemon
+ */
+ nm_creds_t *creds;
+
+ /**
+ * attribute handler regeisterd at the daemon
+ */
+ nm_handler_t *handler;
+};
+
+/**
+ * NM plugin processing routine, creates and handles NMVPNPlugin
+ */
+static job_requeue_t run(private_nm_plugin_t *this)
+{
+ this->loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(this->loop);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_nm_plugin_t *this)
+{
+ if (this->loop)
+ {
+ if (g_main_loop_is_running(this->loop))
+ {
+ g_main_loop_quit(this->loop);
+ }
+ g_main_loop_unref(this->loop);
+ }
+ if (this->plugin)
+ {
+ g_object_unref(this->plugin);
+ }
+ charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ this->creds->destroy(this->creds);
+ this->handler->destroy(this->handler);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *nm_plugin_create()
+{
+ private_nm_plugin_t *this = malloc_thing(private_nm_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->loop = NULL;
+ g_type_init ();
+ if (!g_thread_supported())
+ {
+ g_thread_init(NULL);
+ }
+
+ this->creds = nm_creds_create();
+ this->handler = nm_handler_create();
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+ charon->credentials->add_set(charon->credentials, &this->creds->set);
+ this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
+ if (!this->plugin)
+ {
+ DBG1(DBG_CFG, "DBUS binding failed");
+ destroy(this);
+ return NULL;
+ }
+
+ /* bypass file permissions to read from users ssh-agent */
+ charon->keep_cap(charon, CAP_DAC_OVERRIDE);
+
+ charon->processor->queue_job(charon->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL));
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/nm/nm_plugin.h b/src/libcharon/plugins/nm/nm_plugin.h
new file mode 100644
index 000000000..b64b3edf6
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 nm nm
+ * @ingroup cplugins
+ *
+ * @defgroup nm_plugin nm_plugin
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_PLUGIN_H_
+#define NM_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct nm_plugin_t nm_plugin_t;
+
+/**
+ * NetworkManager integration plugin.
+ */
+struct nm_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** NM_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
new file mode 100644
index 000000000..cdf7dc962
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -0,0 +1,629 @@
+/*
+ * Copyright (C) 2008-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 <nm-setting-vpn.h>
+#include <nm-setting-connection.h>
+#include "nm_service.h"
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <config/peer_cfg.h>
+#include <credentials/certificates/x509.h>
+
+#include <stdio.h>
+
+G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
+
+/**
+ * Private data of NMStrongswanPlugin
+ */
+typedef struct {
+ /* implements bus listener interface */
+ listener_t listener;
+ /* IKE_SA we are listening on */
+ ike_sa_t *ike_sa;
+ /* backref to public plugin */
+ NMVPNPlugin *plugin;
+ /* credentials to use for authentication */
+ nm_creds_t *creds;
+ /* attribute handler for DNS/NBNS server information */
+ nm_handler_t *handler;
+ /* name of the connection */
+ char *name;
+} NMStrongswanPluginPrivate;
+
+#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+ NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
+
+/**
+ * convert enumerated handler chunks to a UINT_ARRAY GValue
+ */
+static GValue* handler_to_val(nm_handler_t *handler,
+ configuration_attribute_type_t type)
+{
+ GValue *val;
+ GArray *array;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+
+ enumerator = handler->create_enumerator(handler, type);
+ array = g_array_new (FALSE, TRUE, sizeof (guint32));
+ while (enumerator->enumerate(enumerator, &chunk))
+ {
+ g_array_append_val (array, *(u_int32_t*)chunk.ptr);
+ }
+ enumerator->destroy(enumerator);
+ val = g_slice_new0 (GValue);
+ g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
+ g_value_set_boxed (val, array);
+
+ return val;
+}
+
+/**
+ * signal IPv4 config to NM, set connection as established
+ */
+static void signal_ipv4_config(NMVPNPlugin *plugin,
+ ike_sa_t *ike_sa, child_sa_t *child_sa)
+{
+ GValue *val;
+ GHashTable *config;
+ host_t *me, *other;
+ nm_handler_t *handler;
+
+ config = g_hash_table_new(g_str_hash, g_str_equal);
+ me = ike_sa->get_my_host(ike_sa);
+ other = ike_sa->get_other_host(ike_sa);
+ handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
+
+ /* NM requires a tundev, but netkey does not use one. Passing an invalid
+ * iface makes NM complain, but it accepts it without fiddling on eth0. */
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, "none");
+ g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, me->get_address(me).len * 8);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+
+ val = handler_to_val(handler, INTERNAL_IP4_DNS);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
+
+ val = handler_to_val(handler, INTERNAL_IP4_NBNS);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
+
+ handler->reset(handler);
+
+ nm_vpn_plugin_set_ip4_config(plugin, config);
+}
+
+/**
+ * signal failure to NM, connecting failed
+ */
+static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure)
+{
+ nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
+
+ handler->reset(handler);
+
+ /* TODO: NM does not handle this failure!? */
+ nm_vpn_plugin_failure(plugin, failure);
+ nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
+
+ if (private->ike_sa == ike_sa && state == IKE_DESTROYING)
+ {
+ signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
+
+ if (private->ike_sa == ike_sa && state == CHILD_DESTROYING)
+ {
+ signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_updown
+ */
+static bool child_updown(listener_t *listener, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, bool up)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
+
+ if (private->ike_sa == ike_sa)
+ {
+ if (up)
+ { /* disable initiate-failure-detection hooks */
+ private->listener.ike_state_change = NULL;
+ private->listener.child_state_change = NULL;
+ signal_ipv4_config(private->plugin, ike_sa, child_sa);
+ }
+ else
+ {
+ signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.ike_rekey
+ */
+static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
+
+ if (private->ike_sa == old)
+ { /* follow a rekeyed IKE_SA */
+ private->ike_sa = new;
+ }
+ return TRUE;
+}
+
+/**
+ * Connect function called from NM via DBUS
+ */
+static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
+ GError **err)
+{
+ NMStrongswanPluginPrivate *priv;
+ NMSettingConnection *conn;
+ NMSettingVPN *vpn;
+ identification_t *user = NULL, *gateway = NULL;
+ const char *address, *str;
+ bool virtual, encap, ipcomp;
+ ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ auth_cfg_t *auth;
+ auth_class_t auth_class = AUTH_CLASS_EAP;
+ certificate_t *cert = NULL;
+ x509_t *x509;
+ bool agent = FALSE;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = 10800 /* 3h */,
+ .rekey = 10200 /* 2h50min */,
+ .jitter = 300 /* 5min */
+ }
+ };
+
+ /**
+ * Read parameters
+ */
+ priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection,
+ NM_TYPE_SETTING_CONNECTION));
+ vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
+ NM_TYPE_SETTING_VPN));
+ if (priv->name)
+ {
+ free(priv->name);
+ }
+ priv->name = strdup(nm_setting_connection_get_id(conn));
+ DBG1(DBG_CFG, "received initiate for NetworkManager connection %s",
+ priv->name);
+ DBG4(DBG_CFG, "%s",
+ nm_setting_to_string(NM_SETTING(vpn)));
+ address = nm_setting_vpn_get_data_item(vpn, "address");
+ if (!address || !*address)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Gateway address missing.");
+ return FALSE;
+ }
+ str = nm_setting_vpn_get_data_item(vpn, "virtual");
+ virtual = str && streq(str, "yes");
+ str = nm_setting_vpn_get_data_item(vpn, "encap");
+ encap = str && streq(str, "yes");
+ str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
+ ipcomp = str && streq(str, "yes");
+ str = nm_setting_vpn_get_data_item(vpn, "method");
+ if (str)
+ {
+ if (streq(str, "psk"))
+ {
+ auth_class = AUTH_CLASS_PSK;
+ }
+ else if (streq(str, "agent"))
+ {
+ auth_class = AUTH_CLASS_PUBKEY;
+ agent = TRUE;
+ }
+ else if (streq(str, "key"))
+ {
+ auth_class = AUTH_CLASS_PUBKEY;
+ }
+ }
+
+ /**
+ * Register credentials
+ */
+ priv->creds->clear(priv->creds);
+
+ /* gateway/CA cert */
+ str = nm_setting_vpn_get_data_item(vpn, "certificate");
+ if (str)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, str, BUILD_END);
+ if (!cert)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Loading gateway certificate failed.");
+ return FALSE;
+ }
+ priv->creds->add_certificate(priv->creds, cert);
+
+ x509 = (x509_t*)cert;
+ if (!(x509->get_flags(x509) & X509_CA))
+ { /* For a gateway certificate, we use the cert subject as identity. */
+ gateway = cert->get_subject(cert);
+ gateway = gateway->clone(gateway);
+ DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway);
+ }
+ }
+ else
+ {
+ /* no certificate defined, fall back to system-wide CA certificates */
+ priv->creds->load_ca_dir(priv->creds, NM_CA_DIR);
+ }
+ if (!gateway)
+ {
+ /* If the user configured a CA certificate, we use the IP/DNS
+ * of the gateway as its identity. This identity will be used for
+ * certificate lookup and requires the configured IP/DNS to be
+ * included in the gateway certificate. */
+ gateway = identification_create_from_string((char*)address);
+ DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway);
+ }
+
+ if (auth_class == AUTH_CLASS_EAP)
+ {
+ /* username/password authentication ... */
+ str = nm_setting_vpn_get_data_item(vpn, "user");
+ if (str)
+ {
+ user = identification_create_from_string((char*)str);
+ str = nm_setting_vpn_get_secret(vpn, "password");
+ priv->creds->set_username_password(priv->creds, user, (char*)str);
+ }
+ }
+
+ if (auth_class == AUTH_CLASS_PUBKEY)
+ {
+ /* ... or certificate/private key authenitcation */
+ str = nm_setting_vpn_get_data_item(vpn, "usercert");
+ if (str)
+ {
+ public_key_t *public;
+ private_key_t *private = NULL;
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, str, BUILD_END);
+ if (!cert)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Loading peer certificate failed.");
+ gateway->destroy(gateway);
+ return FALSE;
+ }
+ /* try agent */
+ str = nm_setting_vpn_get_secret(vpn, "agent");
+ if (agent && str)
+ {
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ public->get_type(public),
+ BUILD_AGENT_SOCKET, str,
+ BUILD_PUBLIC_KEY, public,
+ BUILD_END);
+ public->destroy(public);
+ }
+ if (!private)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Connecting to SSH agent failed.");
+ }
+ }
+ /* ... or key file */
+ str = nm_setting_vpn_get_data_item(vpn, "userkey");
+ if (!agent && str)
+ {
+ chunk_t secret;
+
+ secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password");
+ if (secret.ptr)
+ {
+ secret.len = strlen(secret.ptr);
+ }
+ private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ KEY_RSA, BUILD_FROM_FILE, str,
+ BUILD_PASSPHRASE, secret, BUILD_END);
+ if (!private)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Loading private key failed.");
+ }
+ }
+ if (private)
+ {
+ user = cert->get_subject(cert);
+ user = user->clone(user);
+ priv->creds->set_cert_and_key(priv->creds, cert, private);
+ }
+ else
+ {
+ DESTROY_IF(cert);
+ gateway->destroy(gateway);
+ return FALSE;
+ }
+ }
+ }
+
+ if (!user)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Configuration parameters missing.");
+ gateway->destroy(gateway);
+ return FALSE;
+ }
+
+ /**
+ * Set up configurations
+ */
+ ike_cfg = ike_cfg_create(TRUE, encap,
+ "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT);
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg,
+ CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
+ 36000, 0, /* rekey 10h, reauth none */
+ 600, 600, /* jitter, over 10min */
+ TRUE, 0, /* mobike, DPD */
+ virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
+ NULL, FALSE, NULL, NULL); /* pool, mediation */
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
+ auth->add(auth, AUTH_RULE_IDENTITY, user);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY, gateway);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
+ child_cfg = child_cfg_create(priv->name, &lifetime,
+ NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
+ ACTION_NONE, ACTION_NONE, ipcomp, 0);
+ child_cfg->add_proposal(child_cfg, proposal_create_default(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", 0,
+ "255.255.255.255", 65535);
+ child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+
+ /**
+ * Prepare IKE_SA
+ */
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
+ if (!ike_sa->get_peer_cfg(ike_sa))
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ }
+ peer_cfg->destroy(peer_cfg);
+
+ /**
+ * Register listener, enable initiate-failure-detection hooks
+ */
+ priv->ike_sa = ike_sa;
+ priv->listener.ike_state_change = ike_state_change;
+ priv->listener.child_state_change = child_state_change;
+ charon->bus->add_listener(charon->bus, &priv->listener);
+
+ /**
+ * Initiate
+ */
+ if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
+ {
+ charon->bus->remove_listener(charon->bus, &priv->listener);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+ "Initiating failed.");
+ return FALSE;
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return TRUE;
+}
+
+/**
+ * NeedSecrets called from NM via DBUS
+ */
+static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
+ char **setting_name, GError **error)
+{
+ NMSettingVPN *settings;
+ const char *method, *path;
+
+ settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
+ NM_TYPE_SETTING_VPN));
+ method = nm_setting_vpn_get_data_item(settings, "method");
+ if (method)
+ {
+ if (streq(method, "eap"))
+ {
+ if (nm_setting_vpn_get_secret(settings, "password"))
+ {
+ return FALSE;
+ }
+ }
+ else if (streq(method, "agent"))
+ {
+ if (nm_setting_vpn_get_secret(settings, "agent"))
+ {
+ return FALSE;
+ }
+ }
+ else if (streq(method, "key"))
+ {
+ path = nm_setting_vpn_get_data_item(settings, "userkey");
+ if (path)
+ {
+ private_key_t *key;
+ chunk_t secret;
+
+ secret.ptr = (char*)nm_setting_vpn_get_secret(settings, "password");
+ if (secret.ptr)
+ {
+ secret.len = strlen(secret.ptr);
+ }
+ /* try to load/decrypt the private key */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ KEY_RSA, BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE, secret, BUILD_END);
+ if (key)
+ {
+ key->destroy(key);
+ return FALSE;
+ }
+ }
+ }
+ }
+ *setting_name = NM_SETTING_VPN_SETTING_NAME;
+ return TRUE;
+}
+
+/**
+ * Disconnect called from NM via DBUS
+ */
+static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
+{
+ NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ u_int id;
+
+ /* our ike_sa pointer might be invalid, lookup sa */
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (priv->ike_sa == ike_sa)
+ {
+ id = ike_sa->get_unique_id(ike_sa);
+ enumerator->destroy(enumerator);
+ charon->controller->terminate_ike(charon->controller, id,
+ controller_cb_empty, NULL);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
+ "Connection not found.");
+ return FALSE;
+}
+
+/**
+ * Initializer
+ */
+static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
+{
+ NMStrongswanPluginPrivate *priv;
+
+ priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ priv->plugin = NM_VPN_PLUGIN(plugin);
+ memset(&priv->listener.log, 0, sizeof(listener_t));
+ priv->listener.child_updown = child_updown;
+ priv->listener.ike_rekey = ike_rekey;
+}
+
+/**
+ * Class constructor
+ */
+static void nm_strongswan_plugin_class_init(
+ NMStrongswanPluginClass *strongswan_class)
+{
+ NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
+
+ g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
+ sizeof(NMStrongswanPluginPrivate));
+ parent_class->connect = connect_;
+ parent_class->need_secrets = need_secrets;
+ parent_class->disconnect = disconnect;
+}
+
+/**
+ * Object constructor
+ */
+NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
+ nm_handler_t *handler)
+{
+ NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
+ NM_TYPE_STRONGSWAN_PLUGIN,
+ NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
+ NULL);
+ if (plugin)
+ {
+ NMStrongswanPluginPrivate *priv;
+
+ priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ priv->creds = creds;
+ priv->handler = handler;
+ priv->name = NULL;
+ }
+ return plugin;
+}
+
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h
new file mode 100644
index 000000000..b00000b6f
--- /dev/null
+++ b/src/libcharon/plugins/nm/nm_service.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008-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 nm_service nm_service
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_SERVICE_H_
+#define NM_SERVICE_H_
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include <nm-vpn-plugin.h>
+
+#include "nm_creds.h"
+#include "nm_handler.h"
+
+#define NM_TYPE_STRONGSWAN_PLUGIN (nm_strongswan_plugin_get_type ())
+#define NM_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPlugin))
+#define NM_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
+#define NM_IS_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
+#define NM_IS_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
+#define NM_STRONGSWAN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
+
+#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
+#define NM_DBUS_INTERFACE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
+#define NM_DBUS_PATH_STRONGSWAN "/org/freedesktop/NetworkManager/strongswan"
+
+typedef struct {
+ NMVPNPlugin parent;
+} NMStrongswanPlugin;
+
+typedef struct {
+ NMVPNPluginClass parent;
+} NMStrongswanPluginClass;
+
+GType nm_strongswan_plugin_get_type(void);
+
+NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
+ nm_handler_t *handler);
+
+#endif /** NM_SERVICE_H_ @}*/
diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am
new file mode 100644
index 000000000..f8830d42e
--- /dev/null
+++ b/src/libcharon/plugins/resolve/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+ -DRESOLV_CONF=\"${resolv_conf}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-resolve.la
+else
+plugin_LTLIBRARIES = libstrongswan-resolve.la
+endif
+
+libstrongswan_resolve_la_SOURCES = \
+ resolve_plugin.h resolve_plugin.c \
+ resolve_handler.h resolve_handler.c
+
+libstrongswan_resolve_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in
new file mode 100644
index 000000000..92ee85539
--- /dev/null
+++ b/src/libcharon/plugins/resolve/Makefile.in
@@ -0,0 +1,591 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/resolve
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_resolve_la_LIBADD =
+am_libstrongswan_resolve_la_OBJECTS = resolve_plugin.lo \
+ resolve_handler.lo
+libstrongswan_resolve_la_OBJECTS = \
+ $(am_libstrongswan_resolve_la_OBJECTS)
+libstrongswan_resolve_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_resolve_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_resolve_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_resolve_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_resolve_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_resolve_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+ -DRESOLV_CONF=\"${resolv_conf}\"
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-resolve.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-resolve.la
+libstrongswan_resolve_la_SOURCES = \
+ resolve_plugin.h resolve_plugin.c \
+ resolve_handler.h resolve_handler.c
+
+libstrongswan_resolve_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-resolve.la: $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_DEPENDENCIES)
+ $(libstrongswan_resolve_la_LINK) $(am_libstrongswan_resolve_la_rpath) $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c
new file mode 100644
index 000000000..714c751a6
--- /dev/null
+++ b/src/libcharon/plugins/resolve/resolve_handler.c
@@ -0,0 +1,251 @@
+/*
+ * 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 "resolve_handler.h"
+
+#include <unistd.h>
+
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_resolve_handler_t private_resolve_handler_t;
+
+/**
+ * Private data of an resolve_handler_t object.
+ */
+struct private_resolve_handler_t {
+
+ /**
+ * Public resolve_handler_t interface.
+ */
+ resolve_handler_t public;
+
+ /**
+ * resolv.conf file to use
+ */
+ char *file;
+
+ /**
+ * Mutex to access file exclusively
+ */
+ mutex_t *mutex;
+};
+
+/**
+ * Implementation of attribute_handler_t.handle
+ */
+static bool handle(private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ FILE *in, *out;
+ char buf[1024];
+ host_t *addr;
+ size_t len;
+ bool handled = FALSE;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ addr = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ addr = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!addr || addr->is_anyaddr(addr))
+ {
+ DESTROY_IF(addr);
+ return FALSE;
+ }
+ this->mutex->lock(this->mutex);
+
+ in = fopen(this->file, "r");
+ /* allows us to stream from in to out */
+ unlink(this->file);
+ out = fopen(this->file, "w");
+ if (out)
+ {
+ fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server);
+ DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
+ handled = TRUE;
+
+ /* copy rest of the file */
+ if (in)
+ {
+ while ((len = fread(buf, 1, sizeof(buf), in)))
+ {
+ ignore_result(fwrite(buf, 1, len, out));
+ }
+ }
+ fclose(out);
+ }
+ if (in)
+ {
+ fclose(in);
+ }
+ this->mutex->unlock(this->mutex);
+ addr->destroy(addr);
+
+ if (!handled)
+ {
+ DBG1(DBG_IKE, "adding DNS server failed", this->file);
+ }
+ return handled;
+}
+
+/**
+ * Implementation of attribute_handler_t.release
+ */
+static void release(private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ FILE *in, *out;
+ char line[1024], matcher[512], *pos;
+ host_t *addr;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+
+ this->mutex->lock(this->mutex);
+
+ in = fopen(this->file, "r");
+ if (in)
+ {
+ /* allows us to stream from in to out */
+ unlink(this->file);
+ out = fopen(this->file, "w");
+ if (out)
+ {
+ addr = host_create_from_chunk(family, data, 0);
+ snprintf(matcher, sizeof(matcher),
+ "nameserver %H # by strongSwan, from %Y\n",
+ addr, server);
+
+ /* copy all, but matching line */
+ while ((pos = fgets(line, sizeof(line), in)))
+ {
+ if (strneq(line, matcher, strlen(matcher)))
+ {
+ DBG1(DBG_IKE, "removing DNS server %H from %s",
+ addr, this->file);
+ }
+ else
+ {
+ fputs(line, out);
+ }
+ }
+ addr->destroy(addr);
+ fclose(out);
+ }
+ fclose(in);
+ }
+
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** virtual IP we are requesting */
+ host_t *vip;
+} attribute_enumerator_t;
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate()
+ */
+static bool attribute_enumerate(attribute_enumerator_t *this,
+ configuration_attribute_type_t *type, chunk_t *data)
+{
+ switch (this->vip->get_family(this->vip))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ *data = chunk_empty;
+ /* enumerate only once */
+ this->public.enumerate = (void*)return_false;
+ return TRUE;
+}
+
+/**
+ * Implementation of attribute_handler_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this,
+ identification_t *server, host_t *vip)
+{
+ if (vip)
+ {
+ attribute_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(attribute_enumerator_t);
+ enumerator->public.enumerate = (void*)attribute_enumerate;
+ enumerator->public.destroy = (void*)free;
+ enumerator->vip = vip;
+
+ return &enumerator->public;
+ }
+ return enumerator_create_empty();
+}
+
+/**
+ * Implementation of resolve_handler_t.destroy.
+ */
+static void destroy(private_resolve_handler_t *this)
+{
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+resolve_handler_t *resolve_handler_create()
+{
+ private_resolve_handler_t *this = malloc_thing(private_resolve_handler_t);
+
+ this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
+ this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
+ this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
+ this->public.destroy = (void(*)(resolve_handler_t*))destroy;
+
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->file = lib->settings->get_str(lib->settings,
+ "charon.plugins.resolve.file", RESOLV_CONF);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/resolve/resolve_handler.h b/src/libcharon/plugins/resolve/resolve_handler.h
new file mode 100644
index 000000000..77bf9781c
--- /dev/null
+++ b/src/libcharon/plugins/resolve/resolve_handler.h
@@ -0,0 +1,49 @@
+/*
+ * 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 resolve_handler resolve_handler
+ * @{ @ingroup resolve
+ */
+
+#ifndef RESOLVE_HANDLER_H_
+#define RESOLVE_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct resolve_handler_t resolve_handler_t;
+
+/**
+ * Handle DNS configuration attributes by mangling a resolv.conf file.
+ */
+struct resolve_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Destroy a resolve_handler_t.
+ */
+ void (*destroy)(resolve_handler_t *this);
+};
+
+/**
+ * Create a resolve_handler instance.
+ */
+resolve_handler_t *resolve_handler_create();
+
+#endif /** RESOLVE_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/resolve/resolve_plugin.c b/src/libcharon/plugins/resolve/resolve_plugin.c
new file mode 100644
index 000000000..502129593
--- /dev/null
+++ b/src/libcharon/plugins/resolve/resolve_plugin.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "resolve_plugin.h"
+#include "resolve_handler.h"
+
+#include <hydra.h>
+
+typedef struct private_resolve_plugin_t private_resolve_plugin_t;
+
+/**
+ * private data of resolve plugin
+ */
+struct private_resolve_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ resolve_plugin_t public;
+
+ /**
+ * The registerd DNS attribute handler
+ */
+ resolve_handler_t *handler;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_resolve_plugin_t *this)
+{
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ this->handler->destroy(this->handler);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *resolve_plugin_create()
+{
+ private_resolve_plugin_t *this = malloc_thing(private_resolve_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+ this->handler = resolve_handler_create();
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/resolve/resolve_plugin.h b/src/libcharon/plugins/resolve/resolve_plugin.h
new file mode 100644
index 000000000..0148b10d7
--- /dev/null
+++ b/src/libcharon/plugins/resolve/resolve_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 resolve resolve
+ * @ingroup cplugins
+ *
+ * @defgroup resolve_plugin resolve_plugin
+ * @{ @ingroup resolve
+ */
+
+#ifndef RESOLVE_PLUGIN_H_
+#define RESOLVE_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct resolve_plugin_t resolve_plugin_t;
+
+/**
+ * Plugin that writes received DNS servers in a resolv.conf file.
+ */
+struct resolve_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** RESOLVE_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/smp/Makefile.am b/src/libcharon/plugins/smp/Makefile.am
new file mode 100644
index 000000000..f17235835
--- /dev/null
+++ b/src/libcharon/plugins/smp/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon ${xml_CFLAGS}
+
+AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-smp.la
+else
+plugin_LTLIBRARIES = libstrongswan-smp.la
+endif
+
+libstrongswan_smp_la_SOURCES = \
+ smp.h smp.c
+
+libstrongswan_smp_la_LDFLAGS = -module -avoid-version
+libstrongswan_smp_la_LIBADD = ${xml_LIBS}
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
new file mode 100644
index 000000000..b88283f38
--- /dev/null
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -0,0 +1,586 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/smp
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libstrongswan_smp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libstrongswan_smp_la_OBJECTS = smp.lo
+libstrongswan_smp_la_OBJECTS = $(am_libstrongswan_smp_la_OBJECTS)
+libstrongswan_smp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_smp_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_smp_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_smp_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_smp_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_smp_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon ${xml_CFLAGS}
+
+AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-smp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-smp.la
+libstrongswan_smp_la_SOURCES = \
+ smp.h smp.c
+
+libstrongswan_smp_la_LDFLAGS = -module -avoid-version
+libstrongswan_smp_la_LIBADD = ${xml_LIBS}
+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/smp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/smp/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-smp.la: $(libstrongswan_smp_la_OBJECTS) $(libstrongswan_smp_la_DEPENDENCIES)
+ $(libstrongswan_smp_la_LINK) $(am_libstrongswan_smp_la_rpath) $(libstrongswan_smp_la_OBJECTS) $(libstrongswan_smp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smp.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
new file mode 100644
index 000000000..64820eb45
--- /dev/null
+++ b/src/libcharon/plugins/smp/smp.c
@@ -0,0 +1,768 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+
+#include "smp.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+
+#include <library.h>
+#include <daemon.h>
+#include <threading/thread.h>
+#include <processing/jobs/callback_job.h>
+
+
+typedef struct private_smp_t private_smp_t;
+
+/**
+ * Private data of an smp_t object.
+ */
+struct private_smp_t {
+
+ /**
+ * Public part of smp_t object.
+ */
+ smp_t public;
+
+ /**
+ * XML unix socket fd
+ */
+ int socket;
+
+ /**
+ * job accepting stroke messages
+ */
+ callback_job_t *job;
+};
+
+ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING,
+ "created",
+ "connecting",
+ "established",
+ "rekeying",
+ "deleting",
+);
+
+/**
+ * write a bool into element
+ */
+static void write_bool(xmlTextWriterPtr writer, char *element, bool val)
+{
+ xmlTextWriterWriteElement(writer, element, val ? "true" : "false");
+}
+
+/**
+ * write a identification_t into element
+ */
+static void write_id(xmlTextWriterPtr writer, char *element, identification_t *id)
+{
+ xmlTextWriterStartElement(writer, element);
+ switch (id->get_type(id))
+ {
+ {
+ char *type = "";
+ while (TRUE)
+ {
+ case ID_ANY:
+ type = "any";
+ break;
+ case ID_IPV4_ADDR:
+ type = "ipv4";
+ break;
+ case ID_IPV6_ADDR:
+ type = "ipv6";
+ break;
+ case ID_FQDN:
+ type = "fqdn";
+ break;
+ case ID_RFC822_ADDR:
+ type = "email";
+ break;
+ case ID_DER_ASN1_DN:
+ type = "asn1dn";
+ break;
+ case ID_DER_ASN1_GN:
+ type = "asn1gn";
+ break;
+ }
+ xmlTextWriterWriteAttribute(writer, "type", type);
+ xmlTextWriterWriteFormatString(writer, "%Y", id);
+ break;
+ }
+ default:
+ /* TODO: base64 keyid */
+ xmlTextWriterWriteAttribute(writer, "type", "keyid");
+ break;
+ }
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * write a host_t address into an element
+ */
+static void write_address(xmlTextWriterPtr writer, char *element, host_t *host)
+{
+ xmlTextWriterStartElement(writer, element);
+ xmlTextWriterWriteAttribute(writer, "type",
+ host->get_family(host) == AF_INET ? "ipv4" : "ipv6");
+ if (host->is_anyaddr(host))
+ { /* do not use %any for XML */
+ xmlTextWriterWriteFormatString(writer, "%s",
+ host->get_family(host) == AF_INET ? "0.0.0.0" : "::");
+ }
+ else
+ {
+ xmlTextWriterWriteFormatString(writer, "%H", host);
+ }
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * write networks element
+ */
+static void write_networks(xmlTextWriterPtr writer, char *element,
+ linked_list_t *list)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+
+ xmlTextWriterStartElement(writer, element);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, (void**)&ts))
+ {
+ xmlTextWriterStartElement(writer, "network");
+ xmlTextWriterWriteAttribute(writer, "type",
+ ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? "ipv4" : "ipv6");
+ xmlTextWriterWriteFormatString(writer, "%R", ts);
+ xmlTextWriterEndElement(writer);
+ }
+ enumerator->destroy(enumerator);
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * write a childEnd
+ */
+static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local)
+{
+ linked_list_t *list;
+
+ xmlTextWriterWriteFormatElement(writer, "spi", "%lx",
+ htonl(child->get_spi(child, local)));
+ list = child->get_traffic_selectors(child, local);
+ write_networks(writer, "networks", list);
+}
+
+/**
+ * write a child_sa_t
+ */
+static void write_child(xmlTextWriterPtr writer, child_sa_t *child)
+{
+ child_cfg_t *config;
+
+ config = child->get_config(child);
+
+ xmlTextWriterStartElement(writer, "childsa");
+ xmlTextWriterWriteFormatElement(writer, "reqid", "%d",
+ child->get_reqid(child));
+ xmlTextWriterWriteFormatElement(writer, "childconfig", "%s",
+ config->get_name(config));
+ xmlTextWriterStartElement(writer, "local");
+ write_childend(writer, child, TRUE);
+ xmlTextWriterEndElement(writer);
+ xmlTextWriterStartElement(writer, "remote");
+ write_childend(writer, child, FALSE);
+ xmlTextWriterEndElement(writer);
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * process a ikesalist query request message
+ */
+static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ /* <ikesalist> */
+ xmlTextWriterStartElement(writer, "ikesalist");
+
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ ike_sa_id_t *id;
+ host_t *local, *remote;
+ iterator_t *children;
+ child_sa_t *child_sa;
+
+ id = ike_sa->get_id(ike_sa);
+
+ xmlTextWriterStartElement(writer, "ikesa");
+ xmlTextWriterWriteFormatElement(writer, "id", "%d",
+ ike_sa->get_unique_id(ike_sa));
+ xmlTextWriterWriteFormatElement(writer, "status", "%N",
+ ike_sa_state_lower_names, ike_sa->get_state(ike_sa));
+ xmlTextWriterWriteElement(writer, "role",
+ id->is_initiator(id) ? "initiator" : "responder");
+ xmlTextWriterWriteElement(writer, "peerconfig", ike_sa->get_name(ike_sa));
+
+ /* <local> */
+ local = ike_sa->get_my_host(ike_sa);
+ xmlTextWriterStartElement(writer, "local");
+ xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
+ id->is_initiator(id) ? id->get_initiator_spi(id)
+ : id->get_responder_spi(id));
+ write_id(writer, "identification", ike_sa->get_my_id(ike_sa));
+ write_address(writer, "address", local);
+ xmlTextWriterWriteFormatElement(writer, "port", "%d",
+ local->get_port(local));
+ if (ike_sa->supports_extension(ike_sa, EXT_NATT))
+ {
+ write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_HERE));
+ }
+ xmlTextWriterEndElement(writer);
+ /* </local> */
+
+ /* <remote> */
+ remote = ike_sa->get_other_host(ike_sa);
+ xmlTextWriterStartElement(writer, "remote");
+ xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
+ id->is_initiator(id) ? id->get_responder_spi(id)
+ : id->get_initiator_spi(id));
+ write_id(writer, "identification", ike_sa->get_other_id(ike_sa));
+ write_address(writer, "address", remote);
+ xmlTextWriterWriteFormatElement(writer, "port", "%d",
+ remote->get_port(remote));
+ if (ike_sa->supports_extension(ike_sa, EXT_NATT))
+ {
+ write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_THERE));
+ }
+ xmlTextWriterEndElement(writer);
+ /* </remote> */
+
+ /* <childsalist> */
+ xmlTextWriterStartElement(writer, "childsalist");
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ write_child(writer, child_sa);
+ }
+ children->destroy(children);
+ /* </childsalist> */
+ xmlTextWriterEndElement(writer);
+
+ /* </ikesa> */
+ xmlTextWriterEndElement(writer);
+ }
+ enumerator->destroy(enumerator);
+
+ /* </ikesalist> */
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * process a configlist query request message
+ */
+static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+
+ /* <configlist> */
+ xmlTextWriterStartElement(writer, "configlist");
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ enumerator_t *children;
+ child_cfg_t *child_cfg;
+ ike_cfg_t *ike_cfg;
+ linked_list_t *list;
+
+ if (peer_cfg->get_ike_version(peer_cfg) != 2)
+ { /* only IKEv2 connections yet */
+ continue;
+ }
+
+ /* <peerconfig> */
+ xmlTextWriterStartElement(writer, "peerconfig");
+ xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
+
+ /* TODO: write auth_cfgs */
+
+ /* <ikeconfig> */
+ ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+ xmlTextWriterStartElement(writer, "ikeconfig");
+ xmlTextWriterWriteElement(writer, "local", ike_cfg->get_my_addr(ike_cfg));
+ xmlTextWriterWriteElement(writer, "remote", ike_cfg->get_other_addr(ike_cfg));
+ xmlTextWriterEndElement(writer);
+ /* </ikeconfig> */
+
+ /* <childconfiglist> */
+ xmlTextWriterStartElement(writer, "childconfiglist");
+ children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (children->enumerate(children, &child_cfg))
+ {
+ /* <childconfig> */
+ xmlTextWriterStartElement(writer, "childconfig");
+ xmlTextWriterWriteElement(writer, "name",
+ child_cfg->get_name(child_cfg));
+ list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+ write_networks(writer, "local", list);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
+ write_networks(writer, "remote", list);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ xmlTextWriterEndElement(writer);
+ /* </childconfig> */
+ }
+ children->destroy(children);
+ /* </childconfiglist> */
+ xmlTextWriterEndElement(writer);
+ /* </peerconfig> */
+ xmlTextWriterEndElement(writer);
+ }
+ enumerator->destroy(enumerator);
+ /* </configlist> */
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * callback which logs to a XML writer
+ */
+static bool xml_callback(xmlTextWriterPtr writer, debug_t group, level_t level,
+ ike_sa_t* ike_sa, char* format, va_list args)
+{
+ if (level <= 1)
+ {
+ /* <item> */
+ xmlTextWriterStartElement(writer, "item");
+ xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
+ xmlTextWriterWriteFormatAttribute(writer, "source", "%N", debug_names, group);
+ xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", thread_current_id());
+ xmlTextWriterWriteVFormatString(writer, format, args);
+ xmlTextWriterEndElement(writer);
+ /* </item> */
+ }
+ return TRUE;
+}
+
+/**
+ * process a *terminate control request message
+ */
+static void request_control_terminate(xmlTextReaderPtr reader,
+ xmlTextWriterPtr writer, bool ike)
+{
+ if (xmlTextReaderRead(reader) &&
+ xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
+ {
+ const char *str;
+ u_int32_t id;
+ status_t status;
+
+ str = xmlTextReaderConstValue(reader);
+ if (str == NULL)
+ {
+ DBG1(DBG_CFG, "error parsing XML id string");
+ return;
+ }
+ id = atoi(str);
+ if (!id)
+ {
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (streq(str, ike_sa->get_name(ike_sa)))
+ {
+ ike = TRUE;
+ id = ike_sa->get_unique_id(ike_sa);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ if (!id)
+ {
+ DBG1(DBG_CFG, "error parsing XML id string");
+ return;
+ }
+
+ DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id);
+
+ /* <log> */
+ xmlTextWriterStartElement(writer, "log");
+ if (ike)
+ {
+ status = charon->controller->terminate_ike(
+ charon->controller, id,
+ (controller_cb_t)xml_callback, writer);
+ }
+ else
+ {
+ status = charon->controller->terminate_child(
+ charon->controller, id,
+ (controller_cb_t)xml_callback, writer);
+ }
+ /* </log> */
+ xmlTextWriterEndElement(writer);
+ xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
+ }
+}
+
+/**
+ * process a *initiate control request message
+ */
+static void request_control_initiate(xmlTextReaderPtr reader,
+ xmlTextWriterPtr writer, bool ike)
+{
+ if (xmlTextReaderRead(reader) &&
+ xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
+ {
+ const char *str;
+ status_t status = FAILED;
+ peer_cfg_t *peer;
+ child_cfg_t *child = NULL;
+ enumerator_t *enumerator;
+
+ str = xmlTextReaderConstValue(reader);
+ if (str == NULL)
+ {
+ DBG1(DBG_CFG, "error parsing XML config name string");
+ return;
+ }
+ DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str);
+
+ /* <log> */
+ xmlTextWriterStartElement(writer, "log");
+ peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
+ if (peer)
+ {
+ enumerator = peer->create_child_cfg_enumerator(peer);
+ if (ike)
+ {
+ if (!enumerator->enumerate(enumerator, &child))
+ {
+ child = NULL;
+ }
+ child->get_ref(child);
+ }
+ else
+ {
+ while (enumerator->enumerate(enumerator, &child))
+ {
+ if (streq(child->get_name(child), str))
+ {
+ child->get_ref(child);
+ break;
+ }
+ child = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (child)
+ {
+ status = charon->controller->initiate(charon->controller,
+ peer, child, (controller_cb_t)xml_callback,
+ writer);
+ }
+ else
+ {
+ peer->destroy(peer);
+ }
+ }
+ /* </log> */
+ xmlTextWriterEndElement(writer);
+ xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
+ }
+}
+
+/**
+ * process a query request
+ */
+static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
+{
+ /* <query> */
+ xmlTextWriterStartElement(writer, "query");
+ while (xmlTextReaderRead(reader))
+ {
+ if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
+ {
+ if (streq(xmlTextReaderConstName(reader), "ikesalist"))
+ {
+ request_query_ikesa(reader, writer);
+ break;
+ }
+ if (streq(xmlTextReaderConstName(reader), "configlist"))
+ {
+ request_query_config(reader, writer);
+ break;
+ }
+ }
+ }
+ /* </query> */
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * process a control request
+ */
+static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
+{
+ /* <control> */
+ xmlTextWriterStartElement(writer, "control");
+ while (xmlTextReaderRead(reader))
+ {
+ if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
+ {
+ if (streq(xmlTextReaderConstName(reader), "ikesaterminate"))
+ {
+ request_control_terminate(reader, writer, TRUE);
+ break;
+ }
+ if (streq(xmlTextReaderConstName(reader), "childsaterminate"))
+ {
+ request_control_terminate(reader, writer, FALSE);
+ break;
+ }
+ if (streq(xmlTextReaderConstName(reader), "ikesainitiate"))
+ {
+ request_control_initiate(reader, writer, TRUE);
+ break;
+ }
+ if (streq(xmlTextReaderConstName(reader), "childsainitiate"))
+ {
+ request_control_initiate(reader, writer, FALSE);
+ break;
+ }
+ }
+ }
+ /* </control> */
+ xmlTextWriterEndElement(writer);
+}
+
+/**
+ * process a request message
+ */
+static void request(xmlTextReaderPtr reader, char *id, int fd)
+{
+ xmlTextWriterPtr writer;
+
+ writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
+ if (writer == NULL)
+ {
+ DBG1(DBG_CFG, "opening SMP XML writer failed");
+ return;
+ }
+
+ xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
+ /* <message xmlns="http://www.strongswan.org/smp/1.0"
+ id="id" type="response"> */
+ xmlTextWriterStartElement(writer, "message");
+ xmlTextWriterWriteAttribute(writer, "xmlns",
+ "http://www.strongswan.org/smp/1.0");
+ xmlTextWriterWriteAttribute(writer, "id", id);
+ xmlTextWriterWriteAttribute(writer, "type", "response");
+
+ while (xmlTextReaderRead(reader))
+ {
+ if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
+ {
+ if (streq(xmlTextReaderConstName(reader), "query"))
+ {
+ request_query(reader, writer);
+ break;
+ }
+ if (streq(xmlTextReaderConstName(reader), "control"))
+ {
+ request_control(reader, writer);
+ break;
+ }
+ }
+ }
+ /* </message> and close document */
+ xmlTextWriterEndDocument(writer);
+ xmlFreeTextWriter(writer);
+}
+
+/**
+ * cleanup helper function for open file descriptors
+ */
+static void closefdp(int *fd)
+{
+ close(*fd);
+}
+
+/**
+ * read from a opened connection and process it
+ */
+static job_requeue_t process(int *fdp)
+{
+ int fd = *fdp;
+ bool oldstate;
+ char buffer[4096];
+ size_t len;
+ xmlTextReaderPtr reader;
+ char *id = NULL, *type = NULL;
+
+ thread_cleanup_push((thread_cleanup_t)closefdp, (void*)&fd);
+ oldstate = thread_cancelability(TRUE);
+ len = read(fd, buffer, sizeof(buffer));
+ thread_cancelability(oldstate);
+ thread_cleanup_pop(FALSE);
+ if (len <= 0)
+ {
+ close(fd);
+ DBG2(DBG_CFG, "SMP XML connection closed");
+ return JOB_REQUEUE_NONE;
+ }
+ DBG3(DBG_CFG, "got XML request: %b", buffer, len);
+
+ reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
+ if (reader == NULL)
+ {
+ DBG1(DBG_CFG, "opening SMP XML reader failed");
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ /* read message type and id */
+ while (xmlTextReaderRead(reader))
+ {
+ if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT &&
+ streq(xmlTextReaderConstName(reader), "message"))
+ {
+ id = xmlTextReaderGetAttribute(reader, "id");
+ type = xmlTextReaderGetAttribute(reader, "type");
+ break;
+ }
+ }
+
+ /* process message */
+ if (id && type)
+ {
+ if (streq(type, "request"))
+ {
+ request(reader, id, fd);
+ }
+ else
+ {
+ /* response(reader, id) */
+ }
+ }
+ xmlFreeTextReader(reader);
+ return JOB_REQUEUE_FAIR;;
+}
+
+/**
+ * accept from XML socket and create jobs to process connections
+ */
+static job_requeue_t dispatch(private_smp_t *this)
+{
+ struct sockaddr_un strokeaddr;
+ int fd, *fdp, strokeaddrlen = sizeof(strokeaddr);
+ callback_job_t *job;
+ bool oldstate;
+
+ /* wait for connections, but allow thread to terminate */
+ oldstate = thread_cancelability(TRUE);
+ fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
+ thread_cancelability(oldstate);
+
+ if (fd < 0)
+ {
+ DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
+ sleep(1);
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ fdp = malloc_thing(int);
+ *fdp = fd;
+ job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
+ charon->processor->queue_job(charon->processor, (job_t*)job);
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implementation of itnerface_t.destroy.
+ */
+static void destroy(private_smp_t *this)
+{
+ this->job->cancel(this->job);
+ close(this->socket);
+ free(this);
+}
+
+/*
+ * Described in header file
+ */
+plugin_t *smp_plugin_create()
+{
+ struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
+ private_smp_t *this = malloc_thing(private_smp_t);
+ mode_t old;
+
+ this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
+
+ /* set up unix socket */
+ this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (this->socket == -1)
+ {
+ DBG1(DBG_CFG, "could not create XML socket");
+ free(this);
+ return NULL;
+ }
+
+ unlink(unix_addr.sun_path);
+ old = umask(~(S_IRWXU | S_IRWXG));
+ if (bind(this->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0)
+ {
+ DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
+ close(this->socket);
+ free(this);
+ return NULL;
+ }
+ umask(old);
+ if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0)
+ {
+ DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
+ }
+
+ if (listen(this->socket, 5) < 0)
+ {
+ DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
+ close(this->socket);
+ free(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/smp/smp.h b/src/libcharon/plugins/smp/smp.h
new file mode 100644
index 000000000..74c85fb5f
--- /dev/null
+++ b/src/libcharon/plugins/smp/smp.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007-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 smp smp
+ * @ingroup cplugins
+ *
+ * @defgroup smp_i smp
+ * @{ @ingroup smp
+ */
+
+#ifndef SMP_H_
+#define SMP_H_
+
+#include <plugins/plugin.h>
+
+typedef struct smp_t smp_t;
+
+/**
+ * SMP configuration and control interface.
+ *
+ * The SMP interface uses a socket and a to communicate. The syntax is strict
+ * XML, defined in the schema.xml specification.
+ */
+struct smp_t {
+
+ /**
+ * implements the plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** XML_H_ @}*/
diff --git a/src/libcharon/plugins/socket_default/Makefile.am b/src/libcharon/plugins/socket_default/Makefile.am
new file mode 100644
index 000000000..635a1c548
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-socket-default.la
+else
+plugin_LTLIBRARIES = libstrongswan-socket-default.la
+endif
+
+libstrongswan_socket_default_la_SOURCES = \
+ socket_default_socket.h socket_default_socket.c \
+ socket_default_plugin.h socket_default_plugin.c
+
+libstrongswan_socket_default_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
new file mode 100644
index 000000000..03c438acd
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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_default
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_socket_default_la_LIBADD =
+am_libstrongswan_socket_default_la_OBJECTS = socket_default_socket.lo \
+ socket_default_plugin.lo
+libstrongswan_socket_default_la_OBJECTS = \
+ $(am_libstrongswan_socket_default_la_OBJECTS)
+libstrongswan_socket_default_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_socket_default_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_socket_default_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_socket_default_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_socket_default_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_socket_default_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-default.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-default.la
+libstrongswan_socket_default_la_SOURCES = \
+ socket_default_socket.h socket_default_socket.c \
+ socket_default_plugin.h socket_default_plugin.c
+
+libstrongswan_socket_default_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/socket_default/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/socket_default/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-socket-default.la: $(libstrongswan_socket_default_la_OBJECTS) $(libstrongswan_socket_default_la_DEPENDENCIES)
+ $(libstrongswan_socket_default_la_LINK) $(am_libstrongswan_socket_default_la_rpath) $(libstrongswan_socket_default_la_OBJECTS) $(libstrongswan_socket_default_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_default_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_default_socket.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.c b/src/libcharon/plugins/socket_default/socket_default_plugin.c
new file mode 100644
index 000000000..45390ddae
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/socket_default_plugin.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "socket_default_plugin.h"
+
+#include "socket_default_socket.h"
+
+#include <daemon.h>
+
+typedef struct private_socket_default_plugin_t private_socket_default_plugin_t;
+
+/**
+ * Private data of socket plugin
+ */
+struct private_socket_default_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ socket_default_plugin_t public;
+
+ /**
+ * Socket instance.
+ */
+ socket_default_socket_t *socket;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_socket_default_plugin_t *this)
+{
+ charon->socket->remove_socket(charon->socket, &this->socket->socket);
+ this->socket->destroy(this->socket);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *socket_default_plugin_create()
+{
+ private_socket_default_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .socket = socket_default_socket_create(),
+ );
+
+ if (!this->socket)
+ {
+ free(this);
+ return NULL;
+ }
+ charon->socket->add_socket(charon->socket, &this->socket->socket);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.h b/src/libcharon/plugins/socket_default/socket_default_plugin.h
new file mode 100644
index 000000000..6270d93ad
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/socket_default_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_default socket_default
+ * @ingroup cplugins
+ *
+ * @defgroup socket_default_plugin socket_default_plugin
+ * @{ @ingroup socket_default
+ */
+
+#ifndef SOCKET_DEFAULT_PLUGIN_H_
+#define SOCKET_DEFAULT_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct socket_default_plugin_t socket_default_plugin_t;
+
+/**
+ * Default socket implementation plugin.
+ */
+struct socket_default_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** SOCKET_DEFAULT_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
new file mode 100644
index 000000000..bc998182e
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* for struct in6_pktinfo */
+#define _GNU_SOURCE
+#ifdef __sun
+#define _XPG4_2
+#define __EXTENSIONS__
+#endif
+
+#include "socket_default_socket.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
+#include <daemon.h>
+#include <threading/thread.h>
+
+/* Maximum size of a packet */
+#define MAX_PACKET 5000
+
+/* length of non-esp marker */
+#define MARKER_LEN sizeof(u_int32_t)
+
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif /*UDP_ENCAP*/
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif /*UDP_ENCAP_ESPINUDP*/
+
+/* these are not defined on some platforms */
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+#ifndef SOL_IPV6
+#define SOL_IPV6 IPPROTO_IPV6
+#endif
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
+/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
+ * previously defined IPV6_PKTINFO */
+#ifndef IPV6_RECVPKTINFO
+#define IPV6_RECVPKTINFO IPV6_PKTINFO
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}
+#endif
+
+#ifndef HAVE_IN6ADDR_ANY
+static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+#endif
+
+typedef struct private_socket_default_socket_t private_socket_default_socket_t;
+
+/**
+ * Private data of an socket_t object
+ */
+struct private_socket_default_socket_t {
+
+ /**
+ * public functions
+ */
+ socket_default_socket_t public;
+
+ /**
+ * IPv4 socket (500)
+ */
+ int ipv4;
+
+ /**
+ * IPv4 socket for NATT (4500)
+ */
+ int ipv4_natt;
+
+ /**
+ * IPv6 socket (500)
+ */
+ int ipv6;
+
+ /**
+ * IPv6 socket for NATT (4500)
+ */
+ int ipv6_natt;
+};
+
+METHOD(socket_t, receiver, status_t,
+ private_socket_default_socket_t *this, packet_t **packet)
+{
+ char buffer[MAX_PACKET];
+ chunk_t data;
+ packet_t *pkt;
+ host_t *source = NULL, *dest = NULL;
+ int bytes_read = 0, data_offset;
+ bool oldstate;
+
+ fd_set rfds;
+ int max_fd = 0, selected = 0;
+ u_int16_t port = 0;
+
+ FD_ZERO(&rfds);
+
+ if (this->ipv4)
+ {
+ FD_SET(this->ipv4, &rfds);
+ }
+ if (this->ipv4_natt)
+ {
+ FD_SET(this->ipv4_natt, &rfds);
+ }
+ if (this->ipv6)
+ {
+ FD_SET(this->ipv6, &rfds);
+ }
+ if (this->ipv6_natt)
+ {
+ FD_SET(this->ipv6_natt, &rfds);
+ }
+ max_fd = max(max(this->ipv4, this->ipv4_natt), max(this->ipv6, this->ipv6_natt));
+
+ DBG2(DBG_NET, "waiting for data on sockets");
+ oldstate = thread_cancelability(TRUE);
+ if (select(max_fd + 1, &rfds, NULL, NULL, NULL) <= 0)
+ {
+ thread_cancelability(oldstate);
+ return FAILED;
+ }
+ thread_cancelability(oldstate);
+
+ if (FD_ISSET(this->ipv4, &rfds))
+ {
+ port = IKEV2_UDP_PORT;
+ selected = this->ipv4;
+ }
+ if (FD_ISSET(this->ipv4_natt, &rfds))
+ {
+ port = IKEV2_NATT_PORT;
+ selected = this->ipv4_natt;
+ }
+ if (FD_ISSET(this->ipv6, &rfds))
+ {
+ port = IKEV2_UDP_PORT;
+ selected = this->ipv6;
+ }
+ if (FD_ISSET(this->ipv6_natt, &rfds))
+ {
+ port = IKEV2_NATT_PORT;
+ selected = this->ipv6_natt;
+ }
+ if (selected)
+ {
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ struct iovec iov;
+ char ancillary[64];
+ union {
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ } src;
+
+ msg.msg_name = &src;
+ msg.msg_namelen = sizeof(src);
+ iov.iov_base = buffer;
+ iov.iov_len = sizeof(buffer);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ancillary;
+ msg.msg_controllen = sizeof(ancillary);
+ msg.msg_flags = 0;
+ bytes_read = recvmsg(selected, &msg, 0);
+ if (bytes_read < 0)
+ {
+ DBG1(DBG_NET, "error reading socket: %s", strerror(errno));
+ return FAILED;
+ }
+ DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
+
+ if (bytes_read < MARKER_LEN)
+ {
+ DBG3(DBG_NET, "received packet too short (%d bytes)",
+ bytes_read);
+ return FAILED;
+ }
+
+ /* read ancillary data to get destination address */
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
+ {
+ if (cmsgptr->cmsg_len == 0)
+ {
+ DBG1(DBG_NET, "error reading ancillary data");
+ return FAILED;
+ }
+
+#ifdef HAVE_IN6_PKTINFO
+ if (cmsgptr->cmsg_level == SOL_IPV6 &&
+ cmsgptr->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo *pktinfo;
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
+ struct sockaddr_in6 dst;
+
+ memset(&dst, 0, sizeof(dst));
+ memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_port = htons(port);
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+ }
+#endif /* HAVE_IN6_PKTINFO */
+ if (cmsgptr->cmsg_level == SOL_IP &&
+#ifdef IP_PKTINFO
+ cmsgptr->cmsg_type == IP_PKTINFO
+#elif defined(IP_RECVDSTADDR)
+ cmsgptr->cmsg_type == IP_RECVDSTADDR
+#else
+ FALSE
+#endif
+ )
+ {
+ struct in_addr *addr;
+ struct sockaddr_in dst;
+
+#ifdef IP_PKTINFO
+ struct in_pktinfo *pktinfo;
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
+ addr = &pktinfo->ipi_addr;
+#elif defined(IP_RECVDSTADDR)
+ addr = (struct in_addr*)CMSG_DATA(cmsgptr);
+#endif
+ memset(&dst, 0, sizeof(dst));
+ memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
+
+ dst.sin_family = AF_INET;
+ dst.sin_port = htons(port);
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+ }
+ if (dest)
+ {
+ break;
+ }
+ }
+ if (dest == NULL)
+ {
+ DBG1(DBG_NET, "error reading IP header");
+ return FAILED;
+ }
+ source = host_create_from_sockaddr((sockaddr_t*)&src);
+
+ pkt = packet_create();
+ pkt->set_source(pkt, source);
+ pkt->set_destination(pkt, dest);
+ DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
+ data_offset = 0;
+ /* remove non esp marker */
+ if (dest->get_port(dest) == IKEV2_NATT_PORT)
+ {
+ data_offset += MARKER_LEN;
+ }
+ /* fill in packet */
+ data.len = bytes_read - data_offset;
+ data.ptr = malloc(data.len);
+ memcpy(data.ptr, buffer + data_offset, data.len);
+ pkt->set_data(pkt, data);
+ }
+ else
+ {
+ /* oops, shouldn't happen */
+ return FAILED;
+ }
+ /* return packet */
+ *packet = pkt;
+ return SUCCESS;
+}
+
+METHOD(socket_t, sender, status_t,
+ private_socket_default_socket_t *this, packet_t *packet)
+{
+ int sport, skt, family;
+ ssize_t bytes_sent;
+ chunk_t data, marked;
+ host_t *src, *dst;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ data = packet->get_data(packet);
+
+ DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+ /* send data */
+ sport = src->get_port(src);
+ family = dst->get_family(dst);
+ if (sport == IKEV2_UDP_PORT)
+ {
+ if (family == AF_INET)
+ {
+ skt = this->ipv4;
+ }
+ else
+ {
+ skt = this->ipv6;
+ }
+ }
+ else if (sport == IKEV2_NATT_PORT)
+ {
+ if (family == AF_INET)
+ {
+ skt = this->ipv4_natt;
+ }
+ else
+ {
+ skt = this->ipv6_natt;
+ }
+ /* NAT keepalives without marker */
+ if (data.len != 1 || data.ptr[0] != 0xFF)
+ {
+ /* add non esp marker to packet */
+ if (data.len > MAX_PACKET - MARKER_LEN)
+ {
+ DBG1(DBG_NET, "unable to send packet: it's too big (%d bytes)",
+ data.len);
+ return FAILED;
+ }
+ marked = chunk_alloc(data.len + MARKER_LEN);
+ memset(marked.ptr, 0, MARKER_LEN);
+ memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
+ /* let the packet do the clean up for us */
+ packet->set_data(packet, marked);
+ data = marked;
+ }
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to locate a send socket for port %d", sport);
+ return FAILED;
+ }
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_name = dst->get_sockaddr(dst);;
+ msg.msg_namelen = *dst->get_sockaddr_len(dst);
+ iov.iov_base = data.ptr;
+ iov.iov_len = data.len;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ if (!src->is_anyaddr(src))
+ {
+ if (family == AF_INET)
+ {
+#if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
+ struct in_addr *addr;
+ struct sockaddr_in *sin;
+#ifdef IP_PKTINFO
+ char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct in_pktinfo *pktinfo;
+#elif defined(IP_SENDSRCADDR)
+ char buf[CMSG_SPACE(sizeof(struct in_addr))];
+#endif
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IP;
+#ifdef IP_PKTINFO
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in_pktinfo));
+ addr = &pktinfo->ipi_spec_dst;
+#elif defined(IP_SENDSRCADDR)
+ cmsg->cmsg_type = IP_SENDSRCADDR;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ addr = (struct in_addr*)CMSG_DATA(cmsg);
+#endif
+ sin = (struct sockaddr_in*)src->get_sockaddr(src);
+ memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
+#endif /* IP_PKTINFO || IP_SENDSRCADDR */
+ }
+#ifdef HAVE_IN6_PKTINFO
+ else
+ {
+ char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 *sin;
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in6_pktinfo));
+ sin = (struct sockaddr_in6*)src->get_sockaddr(src);
+ memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
+ }
+#endif /* HAVE_IN6_PKTINFO */
+ }
+
+ bytes_sent = sendmsg(skt, &msg, 0);
+
+ if (bytes_sent != data.len)
+ {
+ DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * open a socket to send and receive packets
+ */
+static int open_socket(private_socket_default_socket_t *this,
+ int family, u_int16_t port)
+{
+ int on = TRUE;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ u_int sol, pktinfo = 0;
+ int skt;
+
+ memset(&addr, 0, sizeof(addr));
+ /* precalculate constants depending on address family */
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = htons(port);
+ addrlen = sizeof(struct sockaddr_in);
+ sol = SOL_IP;
+#ifdef IP_PKTINFO
+ pktinfo = IP_PKTINFO;
+#elif defined(IP_RECVDSTADDR)
+ pktinfo = IP_RECVDSTADDR;
+#endif
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ sin6->sin6_family = AF_INET6;
+ memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
+ sin6->sin6_port = htons(port);
+ addrlen = sizeof(struct sockaddr_in6);
+ sol = SOL_IPV6;
+ pktinfo = IPV6_RECVPKTINFO;
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+ if (skt < 0)
+ {
+ DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
+ return 0;
+ }
+ if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ /* bind the socket */
+ if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ /* get additional packet info on receive */
+ if (pktinfo > 0)
+ {
+ if (setsockopt(skt, sol, pktinfo, &on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+ }
+
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
+ {
+ DBG1(DBG_NET, "installing IKE bypass policy failed");
+ }
+
+#ifndef __APPLE__
+ {
+ /* enable UDP decapsulation globally, only for one socket needed */
+ int type = UDP_ENCAP_ESPINUDP;
+ if (family == AF_INET && port == IKEV2_NATT_PORT &&
+ setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
+ }
+ }
+#endif
+ return skt;
+}
+
+METHOD(socket_default_socket_t, destroy, void,
+ private_socket_default_socket_t *this)
+{
+ if (this->ipv4)
+ {
+ close(this->ipv4);
+ }
+ if (this->ipv4_natt)
+ {
+ close(this->ipv4_natt);
+ }
+ if (this->ipv6)
+ {
+ close(this->ipv6);
+ }
+ if (this->ipv6_natt)
+ {
+ close(this->ipv6_natt);
+ }
+ free(this);
+}
+
+/*
+ * See header for description
+ */
+socket_default_socket_t *socket_default_socket_create()
+{
+ private_socket_default_socket_t *this;
+
+ INIT(this,
+ .public = {
+ .socket = {
+ .send = _sender,
+ .receive = _receiver,
+ },
+ .destroy = _destroy,
+ },
+ );
+
+#ifdef __APPLE__
+ {
+ int natt_port = IKEV2_NATT_PORT;
+ if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port,
+ sizeof(natt_port)) != 0)
+ {
+ DBG1(DBG_NET, "could not set net.inet.ipsec.esp_port to %d: %s",
+ natt_port, strerror(errno));
+ }
+ }
+#endif
+
+ this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
+ if (this->ipv4 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
+ }
+ else
+ {
+ this->ipv4_natt = open_socket(this, AF_INET, IKEV2_NATT_PORT);
+ if (this->ipv4_natt == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
+ }
+ }
+
+ this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT);
+ if (this->ipv6 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
+ }
+ else
+ {
+ this->ipv6_natt = open_socket(this, AF_INET6, IKEV2_NATT_PORT);
+ if (this->ipv6_natt == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
+ }
+ }
+
+ if (!this->ipv4 && !this->ipv6)
+ {
+ DBG1(DBG_NET, "could not create any sockets");
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.h b/src/libcharon/plugins/socket_default/socket_default_socket.h
new file mode 100644
index 000000000..755016662
--- /dev/null
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_default_socket socket_default_socket
+ * @{ @ingroup socket_default
+ */
+
+#ifndef SOCKET_DEFAULT_SOCKET_H_
+#define SOCKET_DEFAULT_SOCKET_H_
+
+typedef struct socket_default_socket_t socket_default_socket_t;
+
+#include <network/socket.h>
+
+/**
+ * Default socket, binds to port 500/4500 using any IPv4/IPv6 address.
+ */
+struct socket_default_socket_t {
+
+ /**
+ * Implements the socket_t interface.
+ */
+ socket_t socket;
+
+ /**
+ * Destroy a socket_default_socket_t.
+ */
+ void (*destroy)(socket_default_socket_t *this);
+};
+
+/**
+ * Create a socket_default_socket instance.
+ */
+socket_default_socket_t *socket_default_socket_create();
+
+#endif /** SOCKET_DEFAULT_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.am b/src/libcharon/plugins/socket_dynamic/Makefile.am
new file mode 100644
index 000000000..914945535
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
+else
+plugin_LTLIBRARIES = libstrongswan-socket-dynamic.la
+endif
+
+libstrongswan_socket_dynamic_la_SOURCES = \
+ socket_dynamic_plugin.h socket_dynamic_plugin.c \
+ socket_dynamic_socket.h socket_dynamic_socket.c
+
+libstrongswan_socket_dynamic_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
new file mode 100644
index 000000000..3a5fb3778
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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_dynamic
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_socket_dynamic_la_LIBADD =
+am_libstrongswan_socket_dynamic_la_OBJECTS = socket_dynamic_plugin.lo \
+ socket_dynamic_socket.lo
+libstrongswan_socket_dynamic_la_OBJECTS = \
+ $(am_libstrongswan_socket_dynamic_la_OBJECTS)
+libstrongswan_socket_dynamic_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_socket_dynamic_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_socket_dynamic_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_socket_dynamic_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_socket_dynamic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_socket_dynamic_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-dynamic.la
+libstrongswan_socket_dynamic_la_SOURCES = \
+ socket_dynamic_plugin.h socket_dynamic_plugin.c \
+ socket_dynamic_socket.h socket_dynamic_socket.c
+
+libstrongswan_socket_dynamic_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/socket_dynamic/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/socket_dynamic/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-socket-dynamic.la: $(libstrongswan_socket_dynamic_la_OBJECTS) $(libstrongswan_socket_dynamic_la_DEPENDENCIES)
+ $(libstrongswan_socket_dynamic_la_LINK) $(am_libstrongswan_socket_dynamic_la_rpath) $(libstrongswan_socket_dynamic_la_OBJECTS) $(libstrongswan_socket_dynamic_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_dynamic_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_dynamic_socket.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c
new file mode 100644
index 000000000..3410fc7a4
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "socket_dynamic_plugin.h"
+
+#include "socket_dynamic_socket.h"
+
+#include <daemon.h>
+
+typedef struct private_socket_dynamic_plugin_t private_socket_dynamic_plugin_t;
+
+/**
+ * Private data of socket plugin
+ */
+struct private_socket_dynamic_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ socket_dynamic_plugin_t public;
+
+ /**
+ * Socket instance.
+ */
+ socket_dynamic_socket_t *socket;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_socket_dynamic_plugin_t *this)
+{
+ charon->socket->remove_socket(charon->socket, &this->socket->socket);
+ this->socket->destroy(this->socket);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *socket_dynamic_plugin_create()
+{
+ private_socket_dynamic_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .socket = socket_dynamic_socket_create(),
+ );
+
+ if (!this->socket)
+ {
+ free(this);
+ return NULL;
+ }
+ charon->socket->add_socket(charon->socket, &this->socket->socket);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.h b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.h
new file mode 100644
index 000000000..8d870795f
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_dynamic socket_dynamic
+ * @ingroup cplugins
+ *
+ * @defgroup socket_dynamic_plugin socket_dynamic_plugin
+ * @{ @ingroup socket_dynamic
+ */
+
+#ifndef SOCKET_DYNAMIC_PLUGIN_H_
+#define SOCKET_DYNAMIC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct socket_dynamic_plugin_t socket_dynamic_plugin_t;
+
+/**
+ * Plugin providing a socket that binds ports dynamically.
+ */
+struct socket_dynamic_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** SOCKET_DYNAMIC_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
new file mode 100644
index 000000000..a7db59ce5
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* for struct in6_pktinfo */
+#define _GNU_SOURCE
+
+#include "socket_dynamic_socket.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/rwlock.h>
+#include <utils/hashtable.h>
+
+/* Maximum size of a packet */
+#define MAX_PACKET 5000
+
+/* length of non-esp marker */
+#define MARKER_LEN sizeof(u_int32_t)
+
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif /*UDP_ENCAP*/
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif /*UDP_ENCAP_ESPINUDP*/
+
+/* these are not defined on some platforms */
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+#ifndef SOL_IPV6
+#define SOL_IPV6 IPPROTO_IPV6
+#endif
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
+/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
+ * previously defined IPV6_PKTINFO */
+#ifndef IPV6_RECVPKTINFO
+#define IPV6_RECVPKTINFO IPV6_PKTINFO
+#endif
+
+typedef struct private_socket_dynamic_socket_t private_socket_dynamic_socket_t;
+typedef struct dynsock_t dynsock_t;
+
+/**
+ * Private data of an socket_t object
+ */
+struct private_socket_dynamic_socket_t {
+
+ /**
+ * public functions
+ */
+ socket_dynamic_socket_t public;
+
+ /**
+ * Hashtable of bound sockets
+ */
+ hashtable_t *sockets;
+
+ /**
+ * Lock for sockets hashtable
+ */
+ rwlock_t *lock;
+
+ /**
+ * Notification pipe to signal receiver
+ */
+ int notify[2];
+};
+
+/**
+ * Struct for a dynamically allocated socket
+ */
+struct dynsock_t {
+
+ /**
+ * File descriptor of socket
+ */
+ int fd;
+
+ /**
+ * Address family
+ */
+ int family;
+
+ /**
+ * Bound source port
+ */
+ u_int16_t port;
+};
+
+/**
+ * Hash function for hashtable
+ */
+static u_int hash(dynsock_t *key)
+{
+ return (key->family << 16) | key->port;
+}
+
+/**
+ * Equals function for hashtable
+ */
+static bool equals(dynsock_t *a, dynsock_t *b)
+{
+ return a->family == b->family && a->port == b->port;
+}
+
+/**
+ * Create a fd_set from all bound sockets
+ */
+static int build_fds(private_socket_dynamic_socket_t *this, fd_set *fds)
+{
+ enumerator_t *enumerator;
+ dynsock_t *key, *value;
+ int maxfd;
+
+ FD_ZERO(fds);
+ FD_SET(this->notify[0], fds);
+ maxfd = this->notify[0];
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->sockets->create_enumerator(this->sockets);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ FD_SET(value->fd, fds);
+ maxfd = max(maxfd, value->fd);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return maxfd + 1;
+}
+
+/**
+ * Find the socket select()ed
+ */
+static dynsock_t* scan_fds(private_socket_dynamic_socket_t *this, fd_set *fds)
+{
+ enumerator_t *enumerator;
+ dynsock_t *key, *value, *selected = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->sockets->create_enumerator(this->sockets);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ if (FD_ISSET(value->fd, fds))
+ {
+ selected = value;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return selected;
+}
+
+/**
+ * Receive a packet from a given socket fd
+ */
+static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
+ dynsock_t *skt)
+{
+ host_t *source = NULL, *dest = NULL;
+ ssize_t len;
+ char buffer[MAX_PACKET];
+ chunk_t data;
+ packet_t *packet;
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ struct iovec iov;
+ char ancillary[64];
+ union {
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ } src;
+
+ msg.msg_name = &src;
+ msg.msg_namelen = sizeof(src);
+ iov.iov_base = buffer;
+ iov.iov_len = sizeof(buffer);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ancillary;
+ msg.msg_controllen = sizeof(ancillary);
+ msg.msg_flags = 0;
+ len = recvmsg(skt->fd, &msg, 0);
+ if (len < 0)
+ {
+ DBG1(DBG_NET, "error reading socket: %s", strerror(errno));
+ return NULL;
+ }
+ DBG3(DBG_NET, "received packet %b", buffer, len);
+
+ if (len < MARKER_LEN)
+ {
+ DBG3(DBG_NET, "received packet too short (%d bytes)", len);
+ return NULL;
+ }
+
+ /* read ancillary data to get destination address */
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
+ {
+ if (cmsgptr->cmsg_len == 0)
+ {
+ DBG1(DBG_NET, "error reading ancillary data");
+ return NULL;
+ }
+
+ if (cmsgptr->cmsg_level == SOL_IPV6 &&
+ cmsgptr->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 dst;
+
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
+ memset(&dst, 0, sizeof(dst));
+ memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_port = htons(skt->port);
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+ }
+ if (cmsgptr->cmsg_level == SOL_IP &&
+ cmsgptr->cmsg_type == IP_PKTINFO)
+ {
+ struct in_pktinfo *pktinfo;
+ struct sockaddr_in dst;
+
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
+ memset(&dst, 0, sizeof(dst));
+ memcpy(&dst.sin_addr, &pktinfo->ipi_addr, sizeof(dst.sin_addr));
+
+ dst.sin_family = AF_INET;
+ dst.sin_port = htons(skt->port);
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+ }
+ if (dest)
+ {
+ break;
+ }
+ }
+ if (dest == NULL)
+ {
+ DBG1(DBG_NET, "error reading IP header");
+ return NULL;
+ }
+ source = host_create_from_sockaddr((sockaddr_t*)&src);
+ DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
+ data = chunk_create(buffer, len);
+
+ packet = packet_create();
+ packet->set_source(packet, source);
+ packet->set_destination(packet, dest);
+ /* we assume a non-ESP marker if none of the ports is on 500 */
+ if (dest->get_port(dest) != IKEV2_UDP_PORT &&
+ source->get_port(source) != IKEV2_UDP_PORT)
+ {
+ data = chunk_skip(data, MARKER_LEN);
+ }
+ packet->set_data(packet, chunk_clone(data));
+ return packet;
+}
+
+METHOD(socket_t, receiver, status_t,
+ private_socket_dynamic_socket_t *this, packet_t **packet)
+{
+ dynsock_t *selected;
+ packet_t *pkt;
+ bool oldstate;
+ fd_set fds;
+ int maxfd;
+
+ while (TRUE)
+ {
+ maxfd = build_fds(this, &fds);
+
+ DBG2(DBG_NET, "waiting for data on sockets");
+ oldstate = thread_cancelability(TRUE);
+ if (select(maxfd, &fds, NULL, NULL, NULL) <= 0)
+ {
+ thread_cancelability(oldstate);
+ return FAILED;
+ }
+ thread_cancelability(oldstate);
+
+ if (FD_ISSET(this->notify[0], &fds))
+ { /* got notified, read garbage, rebuild fdset */
+ char buf[1];
+
+ ignore_result(read(this->notify[0], buf, sizeof(buf)));
+ DBG2(DBG_NET, "rebuilding fdset due to newly bound ports");
+ continue;
+ }
+ selected = scan_fds(this, &fds);
+ if (selected)
+ {
+ break;
+ }
+ }
+ pkt = receive_packet(this, selected);
+ if (pkt)
+ {
+ *packet = pkt;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * open a socket to send and receive packets
+ */
+static int open_socket(private_socket_dynamic_socket_t *this,
+ int family, u_int16_t port)
+{
+ int on = TRUE, type = UDP_ENCAP_ESPINUDP;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ u_int sol, pktinfo = 0;
+ int fd;
+
+ memset(&addr, 0, sizeof(addr));
+ /* precalculate constants depending on address family */
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = htons(port);
+ addrlen = sizeof(struct sockaddr_in);
+ sol = SOL_IP;
+ pktinfo = IP_PKTINFO;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ sin6->sin6_family = AF_INET6;
+ memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
+ sin6->sin6_port = htons(port);
+ addrlen = sizeof(struct sockaddr_in6);
+ sol = SOL_IPV6;
+ pktinfo = IPV6_RECVPKTINFO;
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0)
+ {
+ DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
+ return 0;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ /* bind the socket */
+ if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ /* get additional packet info on receive */
+ if (setsockopt(fd, sol, pktinfo, &on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ fd, family))
+ {
+ DBG1(DBG_NET, "installing IKE bypass policy failed");
+ }
+
+ /* enable UDP decapsulation on each socket */
+ if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
+ }
+ return fd;
+}
+
+/**
+ * Find/Create a socket to send from host
+ */
+static dynsock_t *find_socket(private_socket_dynamic_socket_t *this,
+ int family, u_int16_t port)
+{
+ dynsock_t *skt, lookup = {
+ .family = family,
+ .port = port,
+ };
+ char buf[] = {0x01};
+ int fd;
+
+ this->lock->read_lock(this->lock);
+ skt = this->sockets->get(this->sockets, &lookup);
+ this->lock->unlock(this->lock);
+ if (skt)
+ {
+ return skt;
+ }
+ fd = open_socket(this, family, port);
+ if (!fd)
+ {
+ return NULL;
+ }
+ INIT(skt,
+ .family = family,
+ .port = port,
+ .fd = fd,
+ );
+ this->lock->write_lock(this->lock);
+ this->sockets->put(this->sockets, skt, skt);
+ this->lock->unlock(this->lock);
+ /* notify receiver thread to reread socket list */
+ ignore_result(write(this->notify[1], buf, sizeof(buf)));
+
+ return skt;
+}
+
+METHOD(socket_t, sender, status_t,
+ private_socket_dynamic_socket_t *this, packet_t *packet)
+{
+ dynsock_t *skt;
+ host_t *src, *dst;
+ int port, family;
+ ssize_t len;
+ chunk_t data, marked;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ family = src->get_family(src);
+ port = src->get_port(src);
+ skt = find_socket(this, family, port);
+ if (!skt)
+ {
+ return FAILED;
+ }
+
+ data = packet->get_data(packet);
+ DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+ /* use non-ESP marker if none of the ports is 500, not for keep alives */
+ if (port != IKEV2_UDP_PORT && dst->get_port(dst) != IKEV2_UDP_PORT &&
+ !(data.len == 1 && data.ptr[0] == 0xFF))
+ {
+ /* add non esp marker to packet */
+ if (data.len > MAX_PACKET - MARKER_LEN)
+ {
+ DBG1(DBG_NET, "unable to send packet: it's too big (%d bytes)",
+ data.len);
+ return FAILED;
+ }
+ marked = chunk_alloc(data.len + MARKER_LEN);
+ memset(marked.ptr, 0, MARKER_LEN);
+ memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
+ /* let the packet do the clean up for us */
+ packet->set_data(packet, marked);
+ data = marked;
+ }
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_name = dst->get_sockaddr(dst);;
+ msg.msg_namelen = *dst->get_sockaddr_len(dst);
+ iov.iov_base = data.ptr;
+ iov.iov_len = data.len;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ if (!src->is_anyaddr(src))
+ {
+ if (family == AF_INET)
+ {
+ struct in_addr *addr;
+ struct sockaddr_in *sin;
+ char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct in_pktinfo *pktinfo;
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in_pktinfo));
+ addr = &pktinfo->ipi_spec_dst;
+ sin = (struct sockaddr_in*)src->get_sockaddr(src);
+ memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
+ }
+ else
+ {
+ char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 *sin;
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in6_pktinfo));
+ sin = (struct sockaddr_in6*)src->get_sockaddr(src);
+ memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
+ }
+ }
+
+ len = sendmsg(skt->fd, &msg, 0);
+ if (len != data.len)
+ {
+ DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(socket_dynamic_socket_t, destroy, void,
+ private_socket_dynamic_socket_t *this)
+{
+ enumerator_t *enumerator;
+ dynsock_t *key, *value;
+
+ enumerator = this->sockets->create_enumerator(this->sockets);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ close(value->fd);
+ free(value);
+ }
+ enumerator->destroy(enumerator);
+ this->sockets->destroy(this->sockets);
+ this->lock->destroy(this->lock);
+
+ close(this->notify[0]);
+ close(this->notify[1]);
+ free(this);
+}
+
+/*
+ * See header for description
+ */
+socket_dynamic_socket_t *socket_dynamic_socket_create()
+{
+ private_socket_dynamic_socket_t *this;
+
+ INIT(this,
+ .public = {
+ .socket = {
+ .send = _sender,
+ .receive = _receiver,
+ },
+ .destroy = _destroy,
+ },
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ if (pipe(this->notify) != 0)
+ {
+ DBG1(DBG_NET, "creating notify pipe for dynamic socket failed");
+ free(this);
+ return NULL;
+ }
+
+ this->sockets = hashtable_create((void*)hash, (void*)equals, 8);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.h b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.h
new file mode 100644
index 000000000..72551e545
--- /dev/null
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_dynamic_socket socket_dynamic_socket
+ * @{ @ingroup socket_dynamic
+ */
+
+#ifndef SOCKET_DYNAMIC_SOCKET_H_
+#define SOCKET_DYNAMIC_SOCKET_H_
+
+typedef struct socket_dynamic_socket_t socket_dynamic_socket_t;
+
+#include <network/socket.h>
+
+/**
+ * A socket implementation binding to ports on demand as required.
+ */
+struct socket_dynamic_socket_t {
+
+ /**
+ * Implements the socket_t interface.
+ */
+ socket_t socket;
+
+ /**
+ * Destroy a socket_dynamic_socket_t.
+ */
+ void (*destroy)(socket_dynamic_socket_t *this);
+};
+
+/**
+ * Create a socket_dynamic_socket instance.
+ */
+socket_dynamic_socket_t *socket_dynamic_socket_create();
+
+#endif /** SOCKET_DYNAMIC_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/socket_raw/Makefile.am b/src/libcharon/plugins/socket_raw/Makefile.am
new file mode 100644
index 000000000..2109ae5f3
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-socket-raw.la
+else
+plugin_LTLIBRARIES = libstrongswan-socket-raw.la
+endif
+
+libstrongswan_socket_raw_la_SOURCES = \
+ socket_raw_plugin.h socket_raw_plugin.c \
+ socket_raw_socket.h socket_raw_socket.c
+
+libstrongswan_socket_raw_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in
new file mode 100644
index 000000000..65ad6a7a9
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/Makefile.in
@@ -0,0 +1,590 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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_raw
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_socket_raw_la_LIBADD =
+am_libstrongswan_socket_raw_la_OBJECTS = socket_raw_plugin.lo \
+ socket_raw_socket.lo
+libstrongswan_socket_raw_la_OBJECTS = \
+ $(am_libstrongswan_socket_raw_la_OBJECTS)
+libstrongswan_socket_raw_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_socket_raw_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_socket_raw_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_socket_raw_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_socket_raw_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_socket_raw_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-raw.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-raw.la
+libstrongswan_socket_raw_la_SOURCES = \
+ socket_raw_plugin.h socket_raw_plugin.c \
+ socket_raw_socket.h socket_raw_socket.c
+
+libstrongswan_socket_raw_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/socket_raw/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/socket_raw/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-socket-raw.la: $(libstrongswan_socket_raw_la_OBJECTS) $(libstrongswan_socket_raw_la_DEPENDENCIES)
+ $(libstrongswan_socket_raw_la_LINK) $(am_libstrongswan_socket_raw_la_rpath) $(libstrongswan_socket_raw_la_OBJECTS) $(libstrongswan_socket_raw_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_raw_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_raw_socket.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c
new file mode 100644
index 000000000..5b011abcf
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "socket_raw_plugin.h"
+
+#include "socket_raw_socket.h"
+
+#include <daemon.h>
+
+typedef struct private_socket_raw_plugin_t private_socket_raw_plugin_t;
+
+/**
+ * Private data of socket plugin
+ */
+struct private_socket_raw_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ socket_raw_plugin_t public;
+
+ /**
+ * Raw socket instance.
+ */
+ socket_raw_socket_t *socket;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_socket_raw_plugin_t *this)
+{
+ charon->socket->remove_socket(charon->socket, &this->socket->socket);
+ this->socket->destroy(this->socket);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *socket_raw_plugin_create()
+{
+ private_socket_raw_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .socket = socket_raw_socket_create(),
+ );
+
+ if (!this->socket)
+ {
+ free(this);
+ return NULL;
+ }
+ charon->socket->add_socket(charon->socket, &this->socket->socket);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.h b/src/libcharon/plugins/socket_raw/socket_raw_plugin.h
new file mode 100644
index 000000000..a692b7594
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/socket_raw_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_raw socket_raw
+ * @ingroup cplugins
+ *
+ * @defgroup socket_raw_plugin socket_raw_plugin
+ * @{ @ingroup socket_raw
+ */
+
+#ifndef SOCKET_RAW_PLUGIN_H_
+#define SOCKET_RAW_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct socket_raw_plugin_t socket_raw_plugin_t;
+
+/**
+ * RAW socket implementation plugin.
+ */
+struct socket_raw_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** SOCKET_RAW_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
new file mode 100644
index 000000000..e0155fa87
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* for struct in6_pktinfo */
+#define _GNU_SOURCE
+
+#include "socket_raw_socket.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/udp.h>
+#include <linux/types.h>
+#include <linux/filter.h>
+#include <net/if.h>
+
+#include <daemon.h>
+#include <threading/thread.h>
+
+/* Maximum size of a packet */
+#define MAX_PACKET 5000
+
+/* constants for packet handling */
+#define IP_LEN sizeof(struct iphdr)
+#define IP6_LEN sizeof(struct ip6_hdr)
+#define UDP_LEN sizeof(struct udphdr)
+#define MARKER_LEN sizeof(u_int32_t)
+
+/* offsets for packet handling */
+#define IP_PROTO_OFFSET 9
+#define IP6_PROTO_OFFSET 6
+#define IKE_VERSION_OFFSET 17
+#define IKE_LENGTH_OFFSET 24
+
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif /*UDP_ENCAP*/
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif /*UDP_ENCAP_ESPINUDP*/
+
+/* needed for older kernel headers */
+#ifndef IPV6_2292PKTINFO
+#define IPV6_2292PKTINFO 2
+#endif /*IPV6_2292PKTINFO*/
+
+typedef struct private_socket_raw_socket_t private_socket_raw_socket_t;
+
+/**
+ * Private data of an socket_t object
+ */
+struct private_socket_raw_socket_t {
+
+ /**
+ * public functions
+ */
+ socket_raw_socket_t public;
+
+ /**
+ * regular port
+ */
+ int port;
+
+ /**
+ * port used for nat-t
+ */
+ int natt_port;
+
+ /**
+ * raw receiver socket for IPv4
+ */
+ int recv4;
+
+ /**
+ * raw receiver socket for IPv6
+ */
+ int recv6;
+
+ /**
+ * send socket on regular port for IPv4
+ */
+ int send4;
+
+ /**
+ * send socket on regular port for IPv6
+ */
+ int send6;
+
+ /**
+ * send socket on nat-t port for IPv4
+ */
+ int send4_natt;
+
+ /**
+ * send socket on nat-t port for IPv6
+ */
+ int send6_natt;
+};
+
+METHOD(socket_t, receiver, status_t,
+ private_socket_raw_socket_t *this, packet_t **packet)
+{
+ char buffer[MAX_PACKET];
+ chunk_t data;
+ packet_t *pkt;
+ struct udphdr *udp;
+ host_t *source = NULL, *dest = NULL;
+ int bytes_read = 0, data_offset;
+ bool oldstate;
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+
+ if (this->recv4)
+ {
+ FD_SET(this->recv4, &rfds);
+ }
+ if (this->recv6)
+ {
+ FD_SET(this->recv6, &rfds);
+ }
+
+ DBG2(DBG_NET, "waiting for data on raw sockets");
+
+ oldstate = thread_cancelability(TRUE);
+ if (select(max(this->recv4, this->recv6) + 1, &rfds, NULL, NULL, NULL) <= 0)
+ {
+ thread_cancelability(oldstate);
+ return FAILED;
+ }
+ thread_cancelability(oldstate);
+
+ if (this->recv4 && FD_ISSET(this->recv4, &rfds))
+ {
+ /* IPv4 raw sockets return the IP header. We read src/dest
+ * information directly from the raw header */
+ struct iphdr *ip;
+ struct sockaddr_in src, dst;
+
+ bytes_read = recv(this->recv4, buffer, MAX_PACKET, 0);
+ if (bytes_read < 0)
+ {
+ DBG1(DBG_NET, "error reading from IPv4 socket: %s", strerror(errno));
+ return FAILED;
+ }
+ DBG3(DBG_NET, "received IPv4 packet %b", buffer, bytes_read);
+
+ /* read source/dest from raw IP/UDP header */
+ if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
+ {
+ DBG1(DBG_NET, "received IPv4 packet too short (%d bytes)",
+ bytes_read);
+ return FAILED;
+ }
+ ip = (struct iphdr*) buffer;
+ udp = (struct udphdr*) (buffer + IP_LEN);
+ src.sin_family = AF_INET;
+ src.sin_addr.s_addr = ip->saddr;
+ src.sin_port = udp->source;
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = ip->daddr;
+ dst.sin_port = udp->dest;
+ source = host_create_from_sockaddr((sockaddr_t*)&src);
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+
+ pkt = packet_create();
+ pkt->set_source(pkt, source);
+ pkt->set_destination(pkt, dest);
+ DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
+ data_offset = IP_LEN + UDP_LEN;
+ /* remove non esp marker */
+ if (dest->get_port(dest) == IKEV2_NATT_PORT)
+ {
+ data_offset += MARKER_LEN;
+ }
+ /* fill in packet */
+ data.len = bytes_read - data_offset;
+ data.ptr = malloc(data.len);
+ memcpy(data.ptr, buffer + data_offset, data.len);
+ pkt->set_data(pkt, data);
+ }
+ else if (this->recv6 && FD_ISSET(this->recv6, &rfds))
+ {
+ /* IPv6 raw sockets return no IP header. We must query
+ * src/dest via socket options/ancillary data */
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ struct sockaddr_in6 src, dst;
+ struct iovec iov;
+ char ancillary[64];
+
+ msg.msg_name = &src;
+ msg.msg_namelen = sizeof(src);
+ iov.iov_base = buffer;
+ iov.iov_len = sizeof(buffer);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ancillary;
+ msg.msg_controllen = sizeof(ancillary);
+ msg.msg_flags = 0;
+
+ bytes_read = recvmsg(this->recv6, &msg, 0);
+ if (bytes_read < 0)
+ {
+ DBG1(DBG_NET, "error reading from IPv6 socket: %s", strerror(errno));
+ return FAILED;
+ }
+ DBG3(DBG_NET, "received IPv6 packet %b", buffer, bytes_read);
+
+ if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
+ {
+ DBG3(DBG_NET, "received IPv6 packet too short (%d bytes)",
+ bytes_read);
+ return FAILED;
+ }
+
+ /* read ancillary data to get destination address */
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
+ {
+ if (cmsgptr->cmsg_len == 0)
+ {
+ DBG1(DBG_NET, "error reading IPv6 ancillary data");
+ return FAILED;
+ }
+ if (cmsgptr->cmsg_level == SOL_IPV6 &&
+ cmsgptr->cmsg_type == IPV6_2292PKTINFO)
+ {
+ struct in6_pktinfo *pktinfo;
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
+
+ memset(&dst, 0, sizeof(dst));
+ memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
+ dst.sin6_family = AF_INET6;
+ udp = (struct udphdr*) (buffer);
+ dst.sin6_port = udp->dest;
+ src.sin6_port = udp->source;
+ dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+ }
+ }
+ /* ancillary data missing? */
+ if (dest == NULL)
+ {
+ DBG1(DBG_NET, "error reading IPv6 packet header");
+ return FAILED;
+ }
+
+ source = host_create_from_sockaddr((sockaddr_t*)&src);
+
+ pkt = packet_create();
+ pkt->set_source(pkt, source);
+ pkt->set_destination(pkt, dest);
+ DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
+ data_offset = UDP_LEN;
+ /* remove non esp marker */
+ if (dest->get_port(dest) == IKEV2_NATT_PORT)
+ {
+ data_offset += MARKER_LEN;
+ }
+ /* fill in packet */
+ data.len = bytes_read - data_offset;
+ data.ptr = malloc(data.len);
+ memcpy(data.ptr, buffer + data_offset, data.len);
+ pkt->set_data(pkt, data);
+ }
+ else
+ {
+ /* oops, shouldn't happen */
+ return FAILED;
+ }
+
+ /* return packet */
+ *packet = pkt;
+ return SUCCESS;
+}
+
+METHOD(socket_t, sender, status_t,
+ private_socket_raw_socket_t *this, packet_t *packet)
+{
+ int sport, skt, family;
+ ssize_t bytes_sent;
+ chunk_t data, marked;
+ host_t *src, *dst;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ data = packet->get_data(packet);
+
+ DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+ /* send data */
+ sport = src->get_port(src);
+ family = dst->get_family(dst);
+ if (sport == IKEV2_UDP_PORT)
+ {
+ if (family == AF_INET)
+ {
+ skt = this->send4;
+ }
+ else
+ {
+ skt = this->send6;
+ }
+ }
+ else if (sport == IKEV2_NATT_PORT)
+ {
+ if (family == AF_INET)
+ {
+ skt = this->send4_natt;
+ }
+ else
+ {
+ skt = this->send6_natt;
+ }
+ /* NAT keepalives without marker */
+ if (data.len != 1 || data.ptr[0] != 0xFF)
+ {
+ /* add non esp marker to packet */
+ if (data.len > MAX_PACKET - MARKER_LEN)
+ {
+ DBG1(DBG_NET, "unable to send packet: it's too big (%d bytes)",
+ data.len);
+ return FAILED;
+ }
+ marked = chunk_alloc(data.len + MARKER_LEN);
+ memset(marked.ptr, 0, MARKER_LEN);
+ memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
+ /* let the packet do the clean up for us */
+ packet->set_data(packet, marked);
+ data = marked;
+ }
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to locate a send socket for port %d", sport);
+ return FAILED;
+ }
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_name = dst->get_sockaddr(dst);;
+ msg.msg_namelen = *dst->get_sockaddr_len(dst);
+ iov.iov_base = data.ptr;
+ iov.iov_len = data.len;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ if (!src->is_anyaddr(src))
+ {
+ if (family == AF_INET)
+ {
+ char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct in_pktinfo *pktinfo;
+ struct sockaddr_in *sin;
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in_pktinfo));
+ sin = (struct sockaddr_in*)src->get_sockaddr(src);
+ memcpy(&pktinfo->ipi_spec_dst, &sin->sin_addr, sizeof(struct in_addr));
+ }
+ else
+ {
+ char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 *sin;
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_IPV6;
+ cmsg->cmsg_type = IPV6_2292PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in6_pktinfo));
+ sin = (struct sockaddr_in6*)src->get_sockaddr(src);
+ memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
+ }
+ }
+
+ bytes_sent = sendmsg(skt, &msg, 0);
+
+ if (bytes_sent != data.len)
+ {
+ DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * open a socket to send packets
+ */
+static int open_send_socket(private_socket_raw_socket_t *this,
+ int family, u_int16_t port)
+{
+ int on = TRUE;
+ int type = UDP_ENCAP_ESPINUDP;
+ struct sockaddr_storage addr;
+ u_int sol;
+ int skt;
+
+ memset(&addr, 0, sizeof(addr));
+ /* precalculate constants depending on address family */
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = htons(port);
+ sol = SOL_IP;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ sin6->sin6_family = AF_INET6;
+ memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
+ sin6->sin6_port = htons(port);
+ sol = SOL_IPV6;
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+ if (skt < 0)
+ {
+ DBG1(DBG_NET, "could not open send socket: %s", strerror(errno));
+ return 0;
+ }
+
+ if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set SO_REUSEADDR on send socket: %s",
+ strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ /* bind the send socket */
+ if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ DBG1(DBG_NET, "unable to bind send socket: %s",
+ strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ if (family == AF_INET)
+ {
+ /* enable UDP decapsulation globally, only for one socket needed */
+ if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set UDP_ENCAP: %s; NAT-T may fail",
+ strerror(errno));
+ }
+ }
+
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
+ {
+ DBG1(DBG_NET, "installing bypass policy on send socket failed");
+ }
+
+ return skt;
+}
+
+/**
+ * open a socket to receive packets
+ */
+static int open_recv_socket(private_socket_raw_socket_t *this, int family)
+{
+ int skt;
+ int on = TRUE;
+ u_int proto_offset, ip_len, sol, udp_header, ike_header;
+
+ /* precalculate constants depending on address family */
+ switch (family)
+ {
+ case AF_INET:
+ proto_offset = IP_PROTO_OFFSET;
+ ip_len = IP_LEN;
+ sol = SOL_IP;
+ break;
+ case AF_INET6:
+ proto_offset = IP6_PROTO_OFFSET;
+ ip_len = 0; /* IPv6 raw sockets contain no IP header */
+ sol = SOL_IPV6;
+ break;
+ default:
+ return 0;
+ }
+ udp_header = ip_len;
+ ike_header = ip_len + UDP_LEN;
+
+ /* This filter code filters out all non-IKEv2 traffic on
+ * a SOCK_RAW IP_PROTP_UDP socket. Handling of other
+ * IKE versions is done in pluto.
+ */
+ struct sock_filter ikev2_filter_code[] =
+ {
+ /* Destination Port must be either port or natt_port */
+ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 5, 12),
+ /* port */
+ /* IKE version must be 2.0 */
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 10),
+ /* packet length is length in IKEv2 header + ip header + udp header */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + IKE_LENGTH_OFFSET),
+ BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN),
+ BPF_STMT(BPF_RET+BPF_A, 0),
+ /* natt_port */
+ /* nat-t: check for marker */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 5),
+ /* nat-t: IKE version must be 2.0 */
+ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + MARKER_LEN + IKE_VERSION_OFFSET),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3),
+ /* nat-t: packet length is length in IKEv2 header + ip header + udp header + non esp marker */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + MARKER_LEN + IKE_LENGTH_OFFSET),
+ BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN + MARKER_LEN),
+ BPF_STMT(BPF_RET+BPF_A, 0),
+ /* packet doesn't match, ignore */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+ };
+
+ /* Filter struct to use with setsockopt */
+ struct sock_fprog ikev2_filter = {
+ sizeof(ikev2_filter_code) / sizeof(struct sock_filter),
+ ikev2_filter_code
+ };
+
+ /* set up a raw socket */
+ skt = socket(family, SOCK_RAW, IPPROTO_UDP);
+ if (skt < 0)
+ {
+ DBG1(DBG_NET, "unable to create raw socket: %s", strerror(errno));
+ return 0;
+ }
+
+ if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER,
+ &ikev2_filter, sizeof(ikev2_filter)) < 0)
+ {
+ DBG1(DBG_NET, "unable to attach IKEv2 filter to raw socket: %s",
+ strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ if (family == AF_INET6 &&
+ /* we use IPV6_2292PKTINFO, as IPV6_PKTINFO is defined as
+ * 2 or 50 depending on kernel header version */
+ setsockopt(skt, sol, IPV6_2292PKTINFO, &on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set IPV6_PKTINFO on raw socket: %s",
+ strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
+ {
+ DBG1(DBG_NET, "installing bypass policy on receive socket failed");
+ }
+
+ return skt;
+}
+
+METHOD(socket_raw_socket_t, destroy, void,
+ private_socket_raw_socket_t *this)
+{
+ if (this->recv4)
+ {
+ close(this->recv4);
+ }
+ if (this->recv6)
+ {
+ close(this->recv6);
+ }
+ if (this->send4)
+ {
+ close(this->send4);
+ }
+ if (this->send6)
+ {
+ close(this->send6);
+ }
+ if (this->send4_natt)
+ {
+ close(this->send4_natt);
+ }
+ if (this->send6_natt)
+ {
+ close(this->send6_natt);
+ }
+ free(this);
+}
+
+/*
+ * See header for description
+ */
+socket_raw_socket_t *socket_raw_socket_create()
+{
+ private_socket_raw_socket_t *this;
+
+ INIT(this,
+ .public = {
+ .socket = {
+ .send = _sender,
+ .receive = _receiver,
+ },
+ .destroy = _destroy,
+ },
+ );
+
+ this->recv4 = open_recv_socket(this, AF_INET);
+ if (this->recv4 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv4 receive socket, IPv4 disabled");
+ }
+ else
+ {
+ this->send4 = open_send_socket(this, AF_INET, IKEV2_UDP_PORT);
+ if (this->send4 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv4 send socket, IPv4 disabled");
+ close(this->recv4);
+ }
+ else
+ {
+ this->send4_natt = open_send_socket(this, AF_INET, IKEV2_NATT_PORT);
+ if (this->send4_natt == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv4 NAT-T send socket");
+ }
+ }
+ }
+
+ this->recv6 = open_recv_socket(this, AF_INET6);
+ if (this->recv6 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 receive socket, IPv6 disabled");
+ }
+ else
+ {
+ this->send6 = open_send_socket(this, AF_INET6, IKEV2_UDP_PORT);
+ if (this->send6 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 send socket, IPv6 disabled");
+ close(this->recv6);
+ }
+ else
+ {
+ this->send6_natt = open_send_socket(this, AF_INET6, IKEV2_NATT_PORT);
+ if (this->send6_natt == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 NAT-T send socket");
+ }
+ }
+ }
+
+ if (!(this->send4 || this->send6) || !(this->recv4 || this->recv6))
+ {
+ DBG1(DBG_NET, "could not create any sockets");
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.h b/src/libcharon/plugins/socket_raw/socket_raw_socket.h
new file mode 100644
index 000000000..94cf666e8
--- /dev/null
+++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_raw_socket socket_raw_socket
+ * @{ @ingroup socket_raw
+ */
+
+#ifndef SOCKET_RAW_SOCKET_H_
+#define SOCKET_RAW_SOCKET_H_
+
+typedef struct socket_raw_socket_t socket_raw_socket_t;
+
+#include <network/socket.h>
+
+/**
+ * Raw socket, binds to port 500/4500 using any IPv4/IPv6 address.
+ *
+ * This imeplementation uses raw sockets to allow binding of other daemons
+ * (pluto) to UDP/500/4500. An installed "Linux socket filter" filters out
+ * all non-IKEv2 traffic and handles just IKEv2 messages. An other daemon
+ * must handle all traffic separately, e.g. ignore IKEv2 traffic, since charon
+ * handles that.
+ */
+struct socket_raw_socket_t {
+
+ /**
+ * Implements the socket_t interface.
+ */
+ socket_t socket;
+
+ /**
+ * Destroy a socket_raw_socket_t.
+ */
+ void (*destroy)(socket_raw_socket_t *this);
+};
+
+/**
+ * Create a socket_raw_socket instance.
+ */
+socket_raw_socket_t *socket_raw_socket_create();
+
+#endif /** SOCKET_RAW_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/sql/Makefile.am b/src/libcharon/plugins/sql/Makefile.am
new file mode 100644
index 000000000..68b7e8cb2
--- /dev/null
+++ b/src/libcharon/plugins/sql/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+ -DPLUGINS=\""${libstrongswan_plugins}\""
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-sql.la
+else
+plugin_LTLIBRARIES = libstrongswan-sql.la
+endif
+
+libstrongswan_sql_la_SOURCES = \
+ sql_plugin.h sql_plugin.c sql_config.h sql_config.c \
+ sql_cred.h sql_cred.c sql_logger.h sql_logger.c
+
+libstrongswan_sql_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
new file mode 100644
index 000000000..5803dc898
--- /dev/null
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -0,0 +1,591 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/sql
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_sql_la_LIBADD =
+am_libstrongswan_sql_la_OBJECTS = sql_plugin.lo sql_config.lo \
+ sql_cred.lo sql_logger.lo
+libstrongswan_sql_la_OBJECTS = $(am_libstrongswan_sql_la_OBJECTS)
+libstrongswan_sql_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_sql_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_sql_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_sql_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_sql_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_sql_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic \
+ -DPLUGINS=\""${libstrongswan_plugins}\""
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-sql.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-sql.la
+libstrongswan_sql_la_SOURCES = \
+ sql_plugin.h sql_plugin.c sql_config.h sql_config.c \
+ sql_cred.h sql_cred.c sql_logger.h sql_logger.c
+
+libstrongswan_sql_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/sql/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/sql/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-sql.la: $(libstrongswan_sql_la_OBJECTS) $(libstrongswan_sql_la_DEPENDENCIES)
+ $(libstrongswan_sql_la_LINK) $(am_libstrongswan_sql_la_rpath) $(libstrongswan_sql_la_OBJECTS) $(libstrongswan_sql_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_cred.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_logger.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
new file mode 100644
index 000000000..23366898a
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+
+#include "sql_config.h"
+
+#include <daemon.h>
+
+typedef struct private_sql_config_t private_sql_config_t;
+
+/**
+ * Private data of an sql_config_t object
+ */
+struct private_sql_config_t {
+
+ /**
+ * Public part
+ */
+ sql_config_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+};
+
+/**
+ * forward declaration
+ */
+static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
+ identification_t *me, identification_t *other);
+
+/**
+ * build a traffic selector from a SQL query
+ */
+static traffic_selector_t *build_traffic_selector(private_sql_config_t *this,
+ enumerator_t *e, bool *local)
+{
+ int type, protocol, start_port, end_port;
+ chunk_t start_addr, end_addr;
+ traffic_selector_t *ts;
+ enum {
+ TS_LOCAL = 0,
+ TS_REMOTE = 1,
+ TS_LOCAL_DYNAMIC = 2,
+ TS_REMOTE_DYNAMIC = 3,
+ } kind;
+
+ while (e->enumerate(e, &kind, &type, &protocol,
+ &start_addr, &end_addr, &start_port, &end_port))
+ {
+ *local = FALSE;
+ switch (kind)
+ {
+ case TS_LOCAL:
+ *local = TRUE;
+ /* FALL */
+ case TS_REMOTE:
+ ts = traffic_selector_create_from_bytes(protocol, type,
+ start_addr, start_port, end_addr, end_port);
+ break;
+ case TS_LOCAL_DYNAMIC:
+ *local = TRUE;
+ /* FALL */
+ case TS_REMOTE_DYNAMIC:
+ ts = traffic_selector_create_dynamic(protocol,
+ start_port, end_port);
+ break;
+ default:
+ continue;
+ }
+ if (ts)
+ {
+ return ts;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Add traffic selectors to a child config
+ */
+static void add_traffic_selectors(private_sql_config_t *this,
+ child_cfg_t *child, int id)
+{
+ enumerator_t *e;
+ traffic_selector_t *ts;
+ bool local;
+
+ e = this->db->query(this->db,
+ "SELECT kind, type, protocol, "
+ "start_addr, end_addr, start_port, end_port "
+ "FROM traffic_selectors JOIN child_config_traffic_selector "
+ "ON id = traffic_selector WHERE child_cfg = ?",
+ DB_INT, id,
+ DB_INT, DB_INT, DB_INT,
+ DB_BLOB, DB_BLOB, DB_INT, DB_INT);
+ if (e)
+ {
+ while ((ts = build_traffic_selector(this, e, &local)))
+ {
+ child->add_traffic_selector(child, local, ts);
+ }
+ e->destroy(e);
+ }
+}
+
+/**
+ * build a Child configuration from a SQL query
+ */
+static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
+{
+ int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp;
+ char *name, *updown;
+ child_cfg_t *child_cfg;
+
+ if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
+ &updown, &hostaccess, &mode, &dpd, &close, &ipcomp))
+ {
+ lifetime_cfg_t lft = {
+ .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
+ };
+ child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
+ dpd, close, ipcomp, 0);
+ /* TODO: read proposal from db */
+ child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ add_traffic_selectors(this, child_cfg, id);
+ return child_cfg;
+ }
+ return NULL;
+}
+
+/**
+ * Add child configs to peer config
+ */
+static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
+{
+ enumerator_t *e;
+ child_cfg_t *child_cfg;
+
+ e = this->db->query(this->db,
+ "SELECT id, name, lifetime, rekeytime, jitter, "
+ "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
+ "FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
+ "WHERE peer_cfg = ?",
+ DB_INT, id,
+ DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT,
+ DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while ((child_cfg = build_child_cfg(this, e)))
+ {
+ peer->add_child_cfg(peer, child_cfg);
+ }
+ e->destroy(e);
+ }
+}
+
+/**
+ * build a ike configuration from a SQL query
+ */
+static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
+ host_t *my_host, host_t *other_host)
+{
+ int certreq, force_encap;
+ char *local, *remote;
+
+ while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
+ {
+ ike_cfg_t *ike_cfg;
+
+ ike_cfg = ike_cfg_create(certreq, force_encap,
+ local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT);
+ /* TODO: read proposal from db */
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ return ike_cfg;
+ }
+ return NULL;
+}
+
+/**
+ * Query a IKE config by its id
+ */
+static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
+{
+ enumerator_t *e;
+ ike_cfg_t *ike_cfg = NULL;
+
+ e = this->db->query(this->db,
+ "SELECT certreq, force_encap, local, remote "
+ "FROM ike_configs WHERE id = ?",
+ DB_INT, id,
+ DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+ if (e)
+ {
+ ike_cfg = build_ike_cfg(this, e, NULL, NULL);
+ e->destroy(e);
+ }
+ return ike_cfg;
+}
+
+/**
+ * Query a peer config by its id
+ */
+static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
+{
+ enumerator_t *e;
+ peer_cfg_t *peer_cfg = NULL;
+
+ e = this->db->query(this->db,
+ "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
+ "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
+ "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
+ "dpd_delay, virtual, pool, "
+ "mediation, mediated_by, COALESCE(p.type, 0), p.data "
+ "FROM peer_configs AS c "
+ "JOIN identities AS l ON local_id = l.id "
+ "JOIN identities AS r ON remote_id = r.id "
+ "LEFT JOIN identities AS p ON peer_id = p.id "
+ "WHERE id = ?",
+ DB_INT, id,
+ DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_TEXT, DB_TEXT,
+ DB_INT, DB_INT, DB_INT, DB_BLOB);
+ if (e)
+ {
+ peer_cfg = build_peer_cfg(this, e, NULL, NULL);
+ e->destroy(e);
+ }
+ return peer_cfg;
+}
+
+/**
+ * build a peer configuration from a SQL query
+ */
+static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
+ identification_t *me, identification_t *other)
+{
+ int id, ike_cfg, l_type, r_type,
+ cert_policy, uniqueid, auth_method, eap_type, eap_vendor, keyingtries,
+ rekeytime, reauthtime, jitter, overtime, mobike, dpd_delay,
+ mediation, mediated_by, p_type;
+ chunk_t l_data, r_data, p_data;
+ char *name, *virtual, *pool;
+
+ while (e->enumerate(e,
+ &id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data,
+ &cert_policy, &uniqueid, &auth_method, &eap_type, &eap_vendor,
+ &keyingtries, &rekeytime, &reauthtime, &jitter, &overtime, &mobike,
+ &dpd_delay, &virtual, &pool,
+ &mediation, &mediated_by, &p_type, &p_data))
+ {
+ identification_t *local_id, *remote_id, *peer_id = NULL;
+ peer_cfg_t *peer_cfg, *mediated_cfg;
+ ike_cfg_t *ike;
+ host_t *vip = NULL;
+ auth_cfg_t *auth;
+
+ local_id = identification_create_from_encoding(l_type, l_data);
+ remote_id = identification_create_from_encoding(r_type, r_data);
+ if ((me && !me->matches(me, local_id)) ||
+ (other && !other->matches(other, remote_id)))
+ {
+ local_id->destroy(local_id);
+ remote_id->destroy(remote_id);
+ continue;
+ }
+ ike = get_ike_cfg_by_id(this, ike_cfg);
+ mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
+ if (p_type)
+ {
+ peer_id = identification_create_from_encoding(p_type, p_data);
+ }
+ if (virtual)
+ {
+ vip = host_create_from_string(virtual, 0);
+ }
+ if (ike)
+ {
+ peer_cfg = peer_cfg_create(
+ name, 2, ike, cert_policy, uniqueid,
+ keyingtries, rekeytime, reauthtime, jitter, overtime,
+ mobike, dpd_delay, vip, pool,
+ mediation, mediated_cfg, peer_id);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
+ auth->add(auth, AUTH_RULE_IDENTITY, local_id);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_IDENTITY, remote_id);
+ if (eap_type)
+ {
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+ auth->add(auth, AUTH_RULE_EAP_TYPE, eap_type);
+ if (eap_vendor)
+ {
+ auth->add(auth, AUTH_RULE_EAP_VENDOR, eap_vendor);
+ }
+ }
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+ add_child_cfgs(this, peer_cfg, id);
+ return peer_cfg;
+ }
+ DESTROY_IF(ike);
+ DESTROY_IF(mediated_cfg);
+ DESTROY_IF(peer_id);
+ DESTROY_IF(local_id);
+ DESTROY_IF(remote_id);
+ }
+ return NULL;
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name)
+{
+ enumerator_t *e;
+ peer_cfg_t *peer_cfg = NULL;
+
+ e = this->db->query(this->db,
+ "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
+ "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
+ "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
+ "dpd_delay, virtual, pool, "
+ "mediation, mediated_by, COALESCE(p.type, 0), p.data "
+ "FROM peer_configs AS c "
+ "JOIN identities AS l ON local_id = l.id "
+ "JOIN identities AS r ON remote_id = r.id "
+ "LEFT JOIN identities AS p ON peer_id = p.id "
+ "WHERE ike_version = ? AND name = ?",
+ DB_INT, 2, DB_TEXT, name,
+ DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_TEXT, DB_TEXT,
+ DB_INT, DB_INT, DB_INT, DB_BLOB);
+ if (e)
+ {
+ peer_cfg = build_peer_cfg(this, e, NULL, NULL);
+ e->destroy(e);
+ }
+ return peer_cfg;
+}
+
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** reference to context */
+ private_sql_config_t *this;
+ /** filtering own host */
+ host_t *me;
+ /** filtering remote host */
+ host_t *other;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated peer config */
+ ike_cfg_t *current;
+} ike_enumerator_t;
+
+/**
+ * Implementation of ike_enumerator_t.public.enumerate
+ */
+static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
+{
+ DESTROY_IF(this->current);
+ this->current = build_ike_cfg(this->this, this->inner, this->me, this->other);
+ if (this->current)
+ {
+ *cfg = this->current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of ike_enumerator_t.public.destroy
+ */
+static void ike_enumerator_destroy(ike_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
+ host_t *me, host_t *other)
+{
+ ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
+
+ e->this = this;
+ e->me = me;
+ e->other = other;
+ e->current = NULL;
+ e->public.enumerate = (void*)ike_enumerator_enumerate;
+ e->public.destroy = (void*)ike_enumerator_destroy;
+
+ e->inner = this->db->query(this->db,
+ "SELECT certreq, force_encap, local, remote "
+ "FROM ike_configs",
+ DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** reference to context */
+ private_sql_config_t *this;
+ /** filtering own identity */
+ identification_t *me;
+ /** filtering remote identity */
+ identification_t *other;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated peer config */
+ peer_cfg_t *current;
+} peer_enumerator_t;
+
+/**
+ * Implementation of peer_enumerator_t.public.enumerate
+ */
+static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
+{
+ DESTROY_IF(this->current);
+ this->current = build_peer_cfg(this->this, this->inner, this->me, this->other);
+ if (this->current)
+ {
+ *cfg = this->current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of peer_enumerator_t.public.destroy
+ */
+static void peer_enumerator_destroy(peer_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
+
+ e->this = this;
+ e->me = me;
+ e->other = other;
+ e->current = NULL;
+ e->public.enumerate = (void*)peer_enumerator_enumerate;
+ e->public.destroy = (void*)peer_enumerator_destroy;
+
+ /* TODO: only get configs whose IDs match exactly or contain wildcards */
+ e->inner = this->db->query(this->db,
+ "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
+ "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
+ "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
+ "dpd_delay, virtual, pool, "
+ "mediation, mediated_by, COALESCE(p.type, 0), p.data "
+ "FROM peer_configs AS c "
+ "JOIN identities AS l ON local_id = l.id "
+ "JOIN identities AS r ON remote_id = r.id "
+ "LEFT JOIN identities AS p ON peer_id = p.id "
+ "WHERE ike_version = ?",
+ DB_INT, 2,
+ DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
+ DB_INT, DB_TEXT, DB_TEXT,
+ DB_INT, DB_INT, DB_INT, DB_BLOB);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of sql_config_t.destroy.
+ */
+static void destroy(private_sql_config_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+sql_config_t *sql_config_create(database_t *db)
+{
+ private_sql_config_t *this = malloc_thing(private_sql_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(sql_config_t*))destroy;
+
+ this->db = db;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/sql/sql_config.h b/src/libcharon/plugins/sql/sql_config.h
new file mode 100644
index 000000000..700d00a97
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup sql_config_i sql_config
+ * @{ @ingroup sql
+ */
+
+#ifndef SQL_CONFIG_H_
+#define SQL_CONFIG_H_
+
+#include <config/backend.h>
+#include <database/database.h>
+
+typedef struct sql_config_t sql_config_t;
+
+/**
+ * SQL database configuration backend.
+ */
+struct sql_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destry the backend.
+ */
+ void (*destroy)(sql_config_t *this);
+};
+
+/**
+ * Create a sql_config backend instance.
+ *
+ * @param db underlying database
+ * @return backend instance
+ */
+sql_config_t *sql_config_create(database_t *db);
+
+#endif /** SQL_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/sql/sql_cred.c b/src/libcharon/plugins/sql/sql_cred.c
new file mode 100644
index 000000000..12f4ab045
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_cred.c
@@ -0,0 +1,365 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+#include "sql_cred.h"
+
+#include <daemon.h>
+
+typedef struct private_sql_cred_t private_sql_cred_t;
+
+/**
+ * Private data of an sql_cred_t object
+ */
+struct private_sql_cred_t {
+
+ /**
+ * Public part
+ */
+ sql_cred_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+};
+
+/**
+ * enumerator over private keys
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated private key */
+ private_key_t *current;
+} private_enumerator_t;
+
+/**
+ * Implementation of private_enumerator_t.public.enumerate
+ */
+static bool private_enumerator_enumerate(private_enumerator_t *this,
+ private_key_t **key)
+{
+ chunk_t blob;
+ int type;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &type, &blob))
+ {
+ this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_END);
+ if (this->current)
+ {
+ *key = this->current;
+ return TRUE;
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of private_enumerator_t.public.destroy
+ */
+static void private_enumerator_destroy(private_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_private_enumerator.
+ */
+static enumerator_t* create_private_enumerator(private_sql_cred_t *this,
+ key_type_t type,
+ identification_t *id)
+{
+ private_enumerator_t *e;
+
+ e = malloc_thing(private_enumerator_t);
+ e->current = NULL;
+ e->public.enumerate = (void*)private_enumerator_enumerate;
+ e->public.destroy = (void*)private_enumerator_destroy;
+ if (id && id->get_type(id) != ID_ANY)
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT p.type, p.data FROM private_keys AS p "
+ "JOIN private_key_identity AS pi ON p.id = pi.private_key "
+ "JOIN identities AS i ON pi.identity = i.id "
+ "WHERE i.type = ? AND i.data = ? AND (? OR p.type = ?)",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_INT, type == KEY_ANY, DB_INT, type,
+ DB_INT, DB_BLOB);
+ }
+ else
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT type, data FROM private_keys WHERE (? OR type = ?)",
+ DB_INT, type == KEY_ANY, DB_INT, type,
+ DB_INT, DB_BLOB);
+ }
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * enumerator over certificates
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated cert */
+ certificate_t *current;
+} cert_enumerator_t;
+
+/**
+ * Implementation of cert_enumerator_t.public.enumerate
+ */
+static bool cert_enumerator_enumerate(cert_enumerator_t *this,
+ certificate_t **cert)
+{
+ chunk_t blob;
+ int type;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &type, &blob))
+ {
+ this->current = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_END);
+ if (this->current)
+ {
+ *cert = this->current;
+ return TRUE;
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of cert_enumerator_t.public.destroy
+ */
+static void cert_enumerator_destroy(cert_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_cert_enumerator.
+ */
+static enumerator_t* create_cert_enumerator(private_sql_cred_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_enumerator_t *e;
+
+ e = malloc_thing(cert_enumerator_t);
+ e->current = NULL;
+ e->public.enumerate = (void*)cert_enumerator_enumerate;
+ e->public.destroy = (void*)cert_enumerator_destroy;
+ if (id && id->get_type(id) != ID_ANY)
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT c.type, c.data FROM certificates AS c "
+ "JOIN certificate_identity AS ci ON c.id = ci.certificate "
+ "JOIN identities AS i ON ci.identity = i.id "
+ "WHERE i.type = ? AND i.data = ? AND "
+ "(? OR c.type = ?) AND (? OR c.keytype = ?)",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_INT, cert == CERT_ANY, DB_INT, cert,
+ DB_INT, key == KEY_ANY, DB_INT, key,
+ DB_INT, DB_BLOB);
+ }
+ else
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT type, data FROM certificates WHERE "
+ "(? OR type = ?) AND (? OR keytype = ?)",
+ DB_INT, cert == CERT_ANY, DB_INT, cert,
+ DB_INT, key == KEY_ANY, DB_INT, key,
+ DB_INT, DB_BLOB);
+ }
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * enumerator over shared keys
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** own identity */
+ identification_t *me;
+ /** remote identity */
+ identification_t *other;
+ /** currently enumerated private key */
+ shared_key_t *current;
+} shared_enumerator_t;
+
+/**
+ * Implementation of shared_enumerator_t.public.enumerate
+ */
+static bool shared_enumerator_enumerate(shared_enumerator_t *this,
+ shared_key_t **shared,
+ id_match_t *me, id_match_t *other)
+{
+ chunk_t blob;
+ int type;
+
+ DESTROY_IF(this->current);
+ while (this->inner->enumerate(this->inner, &type, &blob))
+ {
+ this->current = shared_key_create(type, chunk_clone(blob));
+ if (this->current)
+ {
+ *shared = this->current;
+ if (me)
+ {
+ *me = this->me ? ID_MATCH_PERFECT : ID_MATCH_ANY;
+ }
+ if (other)
+ {
+ *other = this->other ? ID_MATCH_PERFECT : ID_MATCH_ANY;
+ }
+ return TRUE;
+ }
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+/**
+ * Implementation of shared_enumerator_t.public.destroy
+ */
+static void shared_enumerator_destroy(shared_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of credential_set_t.create_shared_enumerator.
+ */
+static enumerator_t* create_shared_enumerator(private_sql_cred_t *this,
+ shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ shared_enumerator_t *e;
+
+ e = malloc_thing(shared_enumerator_t);
+ e->me = me;
+ e->other = other;
+ e->current = NULL;
+ e->public.enumerate = (void*)shared_enumerator_enumerate;
+ e->public.destroy = (void*)shared_enumerator_destroy;
+ if (!me && !other)
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT type, data FROM shared_secrets WHERE (? OR type = ?)",
+ DB_INT, type == SHARED_ANY, DB_INT, type,
+ DB_INT, DB_BLOB);
+ }
+ else if (me && other)
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT s.type, s.data FROM shared_secrets AS s "
+ "JOIN shared_secret_identity AS sm ON s.id = sm.shared_secret "
+ "JOIN identities AS m ON sm.identity = m.id "
+ "JOIN shared_secret_identity AS so ON s.id = so.shared_secret "
+ "JOIN identities AS o ON so.identity = o.id "
+ "WHERE m.type = ? AND m.data = ? AND o.type = ? AND o.data = ? "
+ "AND (? OR s.type = ?)",
+ DB_INT, me->get_type(me), DB_BLOB, me->get_encoding(me),
+ DB_INT, other->get_type(other), DB_BLOB, other->get_encoding(other),
+ DB_INT, type == SHARED_ANY, DB_INT, type,
+ DB_INT, DB_BLOB);
+ }
+ else
+ {
+ identification_t *id = me ? me : other;
+
+ e->inner = this->db->query(this->db,
+ "SELECT s.type, s.data FROM shared_secrets AS s "
+ "JOIN shared_secret_identity AS si ON s.id = si.shared_secret "
+ "JOIN identities AS i ON si.identity = i.id "
+ "WHERE i.type = ? AND i.data = ? AND (? OR s.type = ?)",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_INT, type == SHARED_ANY, DB_INT, type,
+ DB_INT, DB_BLOB);
+ }
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of credential_set_t.cache_cert.
+ */
+static void cache_cert(private_sql_cred_t *this, certificate_t *cert)
+{
+ /* TODO: implement CRL caching to database */
+}
+
+/**
+ * Implementation of sql_cred_t.destroy.
+ */
+static void destroy(private_sql_cred_t *this)
+{
+ free(this);
+}
+/**
+ * Described in header.
+ */
+sql_cred_t *sql_cred_create(database_t *db)
+{
+ private_sql_cred_t *this = malloc_thing(private_sql_cred_t);
+
+ this->public.set.create_private_enumerator = (void*)create_private_enumerator;
+ this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
+ this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)cache_cert;
+ this->public.destroy = (void(*)(sql_cred_t*))destroy;
+
+ this->db = db;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/sql/sql_cred.h b/src/libcharon/plugins/sql/sql_cred.h
new file mode 100644
index 000000000..7f387398e
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_cred.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup sql_cred_i sql_cred
+ * @{ @ingroup sql
+ */
+
+#ifndef SQL_CRED_H_
+#define SQL_CRED_H_
+
+#include <credentials/credential_set.h>
+#include <database/database.h>
+
+typedef struct sql_cred_t sql_cred_t;
+
+/**
+ * SQL database credential set.
+ */
+struct sql_cred_t {
+
+ /**
+ * Implements credential_set_t interface
+ */
+ credential_set_t set;
+
+ /**
+ * Destry the backend.
+ */
+ void (*destroy)(sql_cred_t *this);
+};
+
+/**
+ * Create a sql_cred backend instance.
+ *
+ * @param db underlying database
+ * @return credential set
+ */
+sql_cred_t *sql_cred_create(database_t *db);
+
+#endif /** SQL_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/sql/sql_logger.c b/src/libcharon/plugins/sql/sql_logger.c
new file mode 100644
index 000000000..d350c4c3d
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_logger.c
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+#include "sql_logger.h"
+
+#include <daemon.h>
+
+typedef struct private_sql_logger_t private_sql_logger_t;
+
+/**
+ * Private data of an sql_logger_t object
+ */
+struct private_sql_logger_t {
+
+ /**
+ * Public part
+ */
+ sql_logger_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+
+ /**
+ * logging level
+ */
+ int level;
+
+ /**
+ * avoid recursive logging
+ */
+ bool recursive;
+};
+
+/**
+ * Implementation of bus_listener_t.log.
+ */
+static bool log_(private_sql_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
+{
+ if (this->recursive)
+ {
+ return TRUE;
+ }
+ this->recursive = TRUE;
+
+ if (ike_sa && level <= this->level)
+ {
+ char buffer[8192];
+ chunk_t local_spi, remote_spi;
+ host_t *local_host, *remote_host;
+ identification_t *local_id, *remote_id;
+ u_int64_t ispi, rspi;
+ ike_sa_id_t *id;
+
+ id = ike_sa->get_id(ike_sa);
+ ispi = id->get_initiator_spi(id);
+ rspi = id->get_responder_spi(id);
+ if (id->is_initiator(id))
+ {
+ local_spi.ptr = (char*)&ispi;
+ remote_spi.ptr = (char*)&rspi;
+ }
+ else
+ {
+ local_spi.ptr = (char*)&rspi;
+ remote_spi.ptr = (char*)&ispi;
+ }
+ local_spi.len = remote_spi.len = sizeof(ispi);
+ local_id = ike_sa->get_my_id(ike_sa);
+ remote_id = ike_sa->get_other_id(ike_sa);
+ local_host = ike_sa->get_my_host(ike_sa);
+ remote_host = ike_sa->get_other_host(ike_sa);
+
+ vsnprintf(buffer, sizeof(buffer), format, args);
+
+ this->db->execute(this->db, NULL, "REPLACE INTO ike_sas ("
+ "local_spi, remote_spi, id, initiator, "
+ "local_id_type, local_id_data, "
+ "remote_id_type, remote_id_data, "
+ "host_family, local_host_data, remote_host_data) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ DB_BLOB, local_spi, DB_BLOB, remote_spi,
+ DB_INT, ike_sa->get_unique_id(ike_sa),
+ DB_INT, id->is_initiator(id),
+ DB_INT, local_id->get_type(local_id),
+ DB_BLOB, local_id->get_encoding(local_id),
+ DB_INT, remote_id->get_type(remote_id),
+ DB_BLOB, remote_id->get_encoding(remote_id),
+ DB_INT, local_host->get_family(local_host),
+ DB_BLOB, local_host->get_address(local_host),
+ DB_BLOB, remote_host->get_address(remote_host));
+ this->db->execute(this->db, NULL, "INSERT INTO logs ("
+ "local_spi, signal, level, msg) VALUES (?, ?, ?, ?)",
+ DB_BLOB, local_spi, DB_INT, group, DB_INT, level,
+ DB_TEXT, buffer);
+ }
+ this->recursive = FALSE;
+ /* always stay registered */
+ return TRUE;
+}
+
+/**
+ * Implementation of sql_logger_t.destroy.
+ */
+static void destroy(private_sql_logger_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+sql_logger_t *sql_logger_create(database_t *db)
+{
+ private_sql_logger_t *this = malloc_thing(private_sql_logger_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
+ this->public.destroy = (void(*)(sql_logger_t*))destroy;
+
+ this->db = db;
+ this->recursive = FALSE;
+
+ this->level = lib->settings->get_int(lib->settings,
+ "charon.plugins.sql.loglevel", -1);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/sql/sql_logger.h b/src/libcharon/plugins/sql/sql_logger.h
new file mode 100644
index 000000000..a933705da
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_logger.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup sql_logger_i sql_logger
+ * @{ @ingroup sql
+ */
+
+#ifndef SQL_LOGGER_H_
+#define SQL_LOGGER_H_
+
+#include <bus/bus.h>
+#include <database/database.h>
+
+typedef struct sql_logger_t sql_logger_t;
+
+/**
+ * SQL database logger.
+ */
+struct sql_logger_t {
+
+ /**
+ * Implements bus_listener_t interface
+ */
+ listener_t listener;
+
+ /**
+ * Destry the backend.
+ */
+ void (*destroy)(sql_logger_t *this);
+};
+
+/**
+ * Create a sql_logger instance.
+ *
+ * @param db underlying database
+ * @return logger instance
+ */
+sql_logger_t *sql_logger_create(database_t *db);
+
+#endif /** SQL_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c
new file mode 100644
index 000000000..e2d2d63b3
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_plugin.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#include "sql_plugin.h"
+
+#include <daemon.h>
+#include "sql_config.h"
+#include "sql_cred.h"
+#include "sql_logger.h"
+
+typedef struct private_sql_plugin_t private_sql_plugin_t;
+
+/**
+ * private data of sql plugin
+ */
+struct private_sql_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ sql_plugin_t public;
+
+ /**
+ * database connection instance
+ */
+ database_t *db;
+
+ /**
+ * configuration backend
+ */
+ sql_config_t *config;
+
+ /**
+ * credential set
+ */
+ sql_cred_t *cred;
+
+ /**
+ * bus listener/logger
+ */
+ sql_logger_t *logger;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_sql_plugin_t *this)
+{
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->cred->set);
+ charon->bus->remove_listener(charon->bus, &this->logger->listener);
+ this->config->destroy(this->config);
+ this->cred->destroy(this->cred);
+ this->logger->destroy(this->logger);
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *sql_plugin_create()
+{
+ char *uri;
+ private_sql_plugin_t *this;
+
+ uri = lib->settings->get_str(lib->settings, "charon.plugins.sql.database", NULL);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "sql plugin: database URI not set");
+ return NULL;
+ }
+
+ this = malloc_thing(private_sql_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->db = lib->db->create(lib->db, uri);
+ if (!this->db)
+ {
+ DBG1(DBG_CFG, "sql plugin failed to connect to database");
+ free(this);
+ return NULL;
+ }
+ this->config = sql_config_create(this->db);
+ this->cred = sql_cred_create(this->db);
+ this->logger = sql_logger_create(this->db);
+
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ charon->credentials->add_set(charon->credentials, &this->cred->set);
+ charon->bus->add_listener(charon->bus, &this->logger->listener);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/sql/sql_plugin.h b/src/libcharon/plugins/sql/sql_plugin.h
new file mode 100644
index 000000000..c6f9ba905
--- /dev/null
+++ b/src/libcharon/plugins/sql/sql_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 sql sql
+ * @ingroup cplugins
+ *
+ * @defgroup sql_plugin sql_plugin
+ * @{ @ingroup sql
+ */
+
+#ifndef SQL_PLUGIN_H_
+#define SQL_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct sql_plugin_t sql_plugin_t;
+
+/**
+ * SQL database configuration plugin
+ */
+struct sql_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** SQL_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
new file mode 100644
index 000000000..40888a40b
--- /dev/null
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -0,0 +1,27 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/stroke
+
+AM_CFLAGS = \
+-rdynamic \
+-DIPSEC_CONFDIR=\"${sysconfdir}\" \
+-DIPSEC_PIDDIR=\"${piddir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-stroke.la
+else
+plugin_LTLIBRARIES = libstrongswan-stroke.la
+endif
+
+libstrongswan_stroke_la_SOURCES = \
+ stroke_plugin.h stroke_plugin.c \
+ stroke_socket.h stroke_socket.c \
+ stroke_config.h stroke_config.c \
+ stroke_control.h stroke_control.c \
+ stroke_cred.h stroke_cred.c \
+ stroke_ca.h stroke_ca.c \
+ stroke_attribute.h stroke_attribute.c \
+ stroke_list.h stroke_list.c \
+ stroke_shared_key.h stroke_shared_key.c
+
+libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
new file mode 100644
index 000000000..8815ba741
--- /dev/null
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -0,0 +1,608 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/stroke
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_stroke_la_LIBADD =
+am_libstrongswan_stroke_la_OBJECTS = stroke_plugin.lo stroke_socket.lo \
+ stroke_config.lo stroke_control.lo stroke_cred.lo stroke_ca.lo \
+ stroke_attribute.lo stroke_list.lo stroke_shared_key.lo
+libstrongswan_stroke_la_OBJECTS = \
+ $(am_libstrongswan_stroke_la_OBJECTS)
+libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_stroke_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_stroke_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_stroke_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_stroke_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_stroke_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/stroke
+
+AM_CFLAGS = \
+-rdynamic \
+-DIPSEC_CONFDIR=\"${sysconfdir}\" \
+-DIPSEC_PIDDIR=\"${piddir}\"
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-stroke.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-stroke.la
+libstrongswan_stroke_la_SOURCES = \
+ stroke_plugin.h stroke_plugin.c \
+ stroke_socket.h stroke_socket.c \
+ stroke_config.h stroke_config.c \
+ stroke_control.h stroke_control.c \
+ stroke_cred.h stroke_cred.c \
+ stroke_ca.h stroke_ca.c \
+ stroke_attribute.h stroke_attribute.c \
+ stroke_list.h stroke_list.c \
+ stroke_shared_key.h stroke_shared_key.c
+
+libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/stroke/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/stroke/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-stroke.la: $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_DEPENDENCIES)
+ $(libstrongswan_stroke_la_LINK) $(am_libstrongswan_stroke_la_rpath) $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_ca.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_control.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_cred.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_shared_key.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
new file mode 100644
index 000000000..1e4615e12
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+#include "stroke_attribute.h"
+
+#include <daemon.h>
+#include <attributes/mem_pool.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_stroke_attribute_t private_stroke_attribute_t;
+
+/**
+ * private data of stroke_attribute
+ */
+struct private_stroke_attribute_t {
+
+ /**
+ * public functions
+ */
+ stroke_attribute_t public;
+
+ /**
+ * list of pools, contains mem_pool_t
+ */
+ linked_list_t *pools;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * find a pool by name
+ */
+static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ mem_pool_t *current, *found = NULL;
+
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(name, current->get_name(current)))
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_stroke_attribute_t *this, char *name, identification_t *id,
+ host_t *requested)
+{
+ mem_pool_t *pool;
+ host_t *addr = NULL;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ addr = pool->acquire_address(pool, id, requested);
+ }
+ this->lock->unlock(this->lock);
+ return addr;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+ private_stroke_attribute_t *this, char *name, host_t *address,
+ identification_t *id)
+{
+ mem_pool_t *pool;
+ bool found = FALSE;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ found = pool->release_address(pool, address, id);
+ }
+ this->lock->unlock(this->lock);
+ return found;
+}
+
+METHOD(stroke_attribute_t, add_pool, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.other.sourceip_mask)
+ {
+ mem_pool_t *pool;
+ host_t *base = NULL;
+ u_int32_t bits = 0;
+
+ /* if %config, add an empty pool, otherwise */
+ if (msg->add_conn.other.sourceip)
+ {
+ DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d",
+ msg->add_conn.name, msg->add_conn.other.sourceip,
+ msg->add_conn.other.sourceip_mask);
+ base = host_create_from_string(msg->add_conn.other.sourceip, 0);
+ if (!base)
+ {
+ DBG1(DBG_CFG, "virtual IP address invalid, discarded");
+ return;
+ }
+ bits = msg->add_conn.other.sourceip_mask;
+ }
+ pool = mem_pool_create(msg->add_conn.name, base, bits);
+ DESTROY_IF(base);
+
+ this->lock->write_lock(this->lock);
+ this->pools->insert_last(this->pools, pool);
+ this->lock->unlock(this->lock);
+ }
+}
+
+METHOD(stroke_attribute_t, del_pool, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ mem_pool_t *pool;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (streq(msg->del_conn.name, pool->get_name(pool)))
+ {
+ this->pools->remove_at(this->pools, enumerator);
+ pool->destroy(pool);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Pool enumerator filter function, converts pool_t to name, size, ...
+ */
+static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
+ void *d1, u_int *size, void *d2, u_int *online,
+ void *d3, u_int *offline)
+{
+ mem_pool_t *pool = *poolp;
+ *name = pool->get_name(pool);
+ *size = pool->get_size(pool);
+ *online = pool->get_online(pool);
+ *offline = pool->get_offline(pool);
+ return TRUE;
+}
+
+METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
+ private_stroke_attribute_t *this)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->pools->create_enumerator(this->pools),
+ (void*)pool_filter,
+ this->lock, (void*)this->lock->unlock);
+}
+
+METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
+ private_stroke_attribute_t *this, char *name)
+{
+ mem_pool_t *pool;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (!pool)
+ {
+ this->lock->unlock(this->lock);
+ return NULL;
+ }
+ return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
+ (void*)this->lock->unlock, this->lock);
+}
+
+METHOD(stroke_attribute_t, destroy, void,
+ private_stroke_attribute_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_attribute_t *stroke_attribute_create()
+{
+ private_stroke_attribute_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .add_pool = _add_pool,
+ .del_pool = _del_pool,
+ .create_pool_enumerator = _create_pool_enumerator,
+ .create_lease_enumerator = _create_lease_enumerator,
+ .destroy = _destroy,
+ },
+ .pools = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.h b/src/libcharon/plugins/stroke/stroke_attribute.h
new file mode 100644
index 000000000..249a9899b
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_attribute.h
@@ -0,0 +1,86 @@
+/*
+ * 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 stroke_attribute stroke_attribute
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_ATTRIBUTE_H_
+#define STROKE_ATTRIBUTE_H_
+
+#include <stroke_msg.h>
+#include <attributes/attribute_provider.h>
+
+typedef struct stroke_attribute_t stroke_attribute_t;
+
+/**
+ * Stroke IKEv2 cfg attribute provider
+ */
+struct stroke_attribute_t {
+
+ /**
+ * Implements attribute provider interface
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Add a virtual IP address pool.
+ *
+ * @param msg stroke message
+ */
+ void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove a virtual IP address pool.
+ *
+ * @param msg stroke message
+ */
+ void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+
+ /**
+ * Create an enumerator over installed pools.
+ *
+ * Enumerator enumerates over
+ * char *pool, u_int size, u_int offline, u_int online.
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_pool_enumerator)(stroke_attribute_t *this);
+
+ /**
+ * Create an enumerator over the leases of a pool.
+ *
+ * Enumerator enumerates over
+ * identification_t *id, host_t *address, bool online
+ *
+ * @param pool name of the pool to enumerate
+ * @return enumerator, NULL if pool not found
+ */
+ enumerator_t* (*create_lease_enumerator)(stroke_attribute_t *this,
+ char *pool);
+
+ /**
+ * Destroy a stroke_attribute instance.
+ */
+ void (*destroy)(stroke_attribute_t *this);
+};
+
+/**
+ * Create a stroke_attribute instance.
+ */
+stroke_attribute_t *stroke_attribute_create();
+
+#endif /** STROKE_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
new file mode 100644
index 000000000..49146f18b
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * 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 "stroke_ca.h"
+#include "stroke_cred.h"
+
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+#include <crypto/hashers/hasher.h>
+
+#include <daemon.h>
+
+typedef struct private_stroke_ca_t private_stroke_ca_t;
+
+/**
+ * private data of stroke_ca
+ */
+struct private_stroke_ca_t {
+
+ /**
+ * public functions
+ */
+ stroke_ca_t public;
+
+ /**
+ * read-write lock to lists
+ */
+ rwlock_t *lock;
+
+ /**
+ * list of starters CA sections and its certificates (ca_section_t)
+ */
+ linked_list_t *sections;
+
+ /**
+ * stroke credentials, stores our CA certificates
+ */
+ stroke_cred_t *cred;
+};
+
+typedef struct ca_section_t ca_section_t;
+
+/**
+ * loaded ipsec.conf CA sections
+ */
+struct ca_section_t {
+
+ /**
+ * name of the CA section
+ */
+ char *name;
+
+ /**
+ * reference to cert in trusted_credential_t
+ */
+ certificate_t *cert;
+
+ /**
+ * CRL URIs
+ */
+ linked_list_t *crl;
+
+ /**
+ * OCSP URIs
+ */
+ linked_list_t *ocsp;
+
+ /**
+ * Hashes of certificates issued by this CA
+ */
+ linked_list_t *hashes;
+
+ /**
+ * Base URI used for certificates from this CA
+ */
+ char *certuribase;
+};
+
+/**
+ * create a new CA section
+ */
+static ca_section_t *ca_section_create(char *name, certificate_t *cert)
+{
+ ca_section_t *ca = malloc_thing(ca_section_t);
+
+ ca->name = strdup(name);
+ ca->crl = linked_list_create();
+ ca->ocsp = linked_list_create();
+ ca->cert = cert;
+ ca->hashes = linked_list_create();
+ ca->certuribase = NULL;
+ return ca;
+}
+
+/**
+ * destroy a ca section entry
+ */
+static void ca_section_destroy(ca_section_t *this)
+{
+ this->crl->destroy_function(this->crl, free);
+ this->ocsp->destroy_function(this->ocsp, free);
+ this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy));
+ free(this->certuribase);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * data to pass to create_inner_cdp
+ */
+typedef struct {
+ private_stroke_ca_t *this;
+ certificate_type_t type;
+ identification_t *id;
+} cdp_data_t;
+
+/**
+ * destroy cdp enumerator data and unlock list
+ */
+static void cdp_data_destroy(cdp_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * inner enumerator constructor for CDP URIs
+ */
+static enumerator_t *create_inner_cdp(ca_section_t *section, cdp_data_t *data)
+{
+ public_key_t *public;
+ enumerator_t *enumerator = NULL;
+ linked_list_t *list;
+
+ if (data->type == CERT_X509_OCSP_RESPONSE)
+ {
+ list = section->ocsp;
+ }
+ else
+ {
+ list = section->crl;
+ }
+
+ public = section->cert->get_public_key(section->cert);
+ if (public)
+ {
+ if (!data->id)
+ {
+ enumerator = list->create_enumerator(list);
+ }
+ else
+ {
+ if (public->has_fingerprint(public, data->id->get_encoding(data->id)))
+ {
+ enumerator = list->create_enumerator(list);
+ }
+ }
+ public->destroy(public);
+ }
+ return enumerator;
+}
+
+/**
+ * inner enumerator constructor for "Hash and URL"
+ */
+static enumerator_t *create_inner_cdp_hashandurl(ca_section_t *section, cdp_data_t *data)
+{
+ enumerator_t *enumerator = NULL, *hash_enum;
+ identification_t *current;
+
+ if (!data->id || !section->certuribase)
+ {
+ return NULL;
+ }
+
+ hash_enum = section->hashes->create_enumerator(section->hashes);
+ while (hash_enum->enumerate(hash_enum, &current))
+ {
+ if (current->matches(current, data->id))
+ {
+ char *url, *hash;
+
+ url = malloc(strlen(section->certuribase) + 40 + 1);
+ strcpy(url, section->certuribase);
+ hash = chunk_to_hex(current->get_encoding(current), NULL, FALSE).ptr;
+ strncat(url, hash, 40);
+ free(hash);
+
+ enumerator = enumerator_create_single(url, free);
+ break;
+ }
+ }
+ hash_enum->destroy(hash_enum);
+ return enumerator;
+}
+
+/**
+ * Implementation of credential_set_t.create_cdp_enumerator.
+ */
+static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this,
+ certificate_type_t type, identification_t *id)
+{
+ cdp_data_t *data;
+
+ switch (type)
+ { /* we serve CRLs, OCSP responders and URLs for "Hash and URL" */
+ case CERT_X509:
+ case CERT_X509_CRL:
+ case CERT_X509_OCSP_RESPONSE:
+ case CERT_ANY:
+ break;
+ default:
+ return NULL;
+ }
+ data = malloc_thing(cdp_data_t);
+ data->this = this;
+ data->type = type;
+ data->id = id;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(this->sections->create_enumerator(this->sections),
+ (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp,
+ data, (void*)cdp_data_destroy);
+}
+/**
+ * Implementation of stroke_ca_t.add.
+ */
+static void add(private_stroke_ca_t *this, stroke_msg_t *msg)
+{
+ certificate_t *cert;
+ ca_section_t *ca;
+
+ if (msg->add_ca.cacert == NULL)
+ {
+ DBG1(DBG_CFG, "missing cacert parameter");
+ return;
+ }
+ cert = this->cred->load_ca(this->cred, msg->add_ca.cacert);
+ if (cert)
+ {
+ ca = ca_section_create(msg->add_ca.name, cert);
+ if (msg->add_ca.crluri)
+ {
+ ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri));
+ }
+ if (msg->add_ca.crluri2)
+ {
+ ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri2));
+ }
+ if (msg->add_ca.ocspuri)
+ {
+ ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri));
+ }
+ if (msg->add_ca.ocspuri2)
+ {
+ ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri2));
+ }
+ if (msg->add_ca.certuribase)
+ {
+ ca->certuribase = strdup(msg->add_ca.certuribase);
+ }
+ this->lock->write_lock(this->lock);
+ this->sections->insert_last(this->sections, ca);
+ this->lock->unlock(this->lock);
+ DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
+ }
+}
+
+/**
+ * Implementation of stroke_ca_t.del.
+ */
+static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ ca_section_t *ca = NULL;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->sections->create_enumerator(this->sections);
+ while (enumerator->enumerate(enumerator, &ca))
+ {
+ if (streq(ca->name, msg->del_ca.name))
+ {
+ this->sections->remove_at(this->sections, enumerator);
+ break;
+ }
+ ca = NULL;
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ if (ca == NULL)
+ {
+ DBG1(DBG_CFG, "no ca named '%s' found\n", msg->del_ca.name);
+ return;
+ }
+ ca_section_destroy(ca);
+ /* TODO: flush cached certs */
+}
+
+/**
+ * list crl or ocsp URIs
+ */
+static void list_uris(linked_list_t *list, char *label, FILE *out)
+{
+ bool first = TRUE;
+ char *uri;
+ enumerator_t *enumerator;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, (void**)&uri))
+ {
+ if (first)
+ {
+ fprintf(out, label);
+ first = FALSE;
+ }
+ else
+ {
+ fprintf(out, " ");
+ }
+ fprintf(out, "'%s'\n", uri);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of stroke_ca_t.check_for_hash_and_url.
+ */
+static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cert)
+{
+ ca_section_t *section;
+ enumerator_t *enumerator;
+
+ hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported");
+ return;
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->sections->create_enumerator(this->sections);
+ while (enumerator->enumerate(enumerator, (void**)&section))
+ {
+ if (section->certuribase && cert->issued_by(cert, section->cert))
+ {
+ chunk_t hash, encoded = cert->get_encoding(cert);
+ hasher->allocate_hash(hasher, encoded, &hash);
+ section->hashes->insert_last(section->hashes,
+ identification_create_from_encoding(ID_KEY_ID, hash));
+ chunk_free(&hash);
+ chunk_free(&encoded);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ hasher->destroy(hasher);
+}
+
+/**
+ * Implementation of stroke_ca_t.list.
+ */
+static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
+{
+ bool first = TRUE;
+ ca_section_t *section;
+ enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->sections->create_enumerator(this->sections);
+ while (enumerator->enumerate(enumerator, (void**)&section))
+ {
+ certificate_t *cert = section->cert;
+ public_key_t *public = cert->get_public_key(cert);
+ chunk_t chunk;
+
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of CA Information Sections:\n");
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+ fprintf(out, " authname: \"%Y\"\n", cert->get_subject(cert));
+
+ /* list authkey and keyid */
+ if (public)
+ {
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
+ {
+ fprintf(out, " authkey: %#B\n", &chunk);
+ }
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &chunk))
+ {
+ fprintf(out, " keyid: %#B\n", &chunk);
+ }
+ public->destroy(public);
+ }
+ list_uris(section->crl, " crluris: ", out);
+ list_uris(section->ocsp, " ocspuris: ", out);
+ if (section->certuribase)
+ {
+ fprintf(out, " certuribase: '%s'\n", section->certuribase);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of stroke_ca_t.destroy
+ */
+static void destroy(private_stroke_ca_t *this)
+{
+ this->sections->destroy_function(this->sections, (void*)ca_section_destroy);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
+{
+ private_stroke_ca_t *this = malloc_thing(private_stroke_ca_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)return_null;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)create_cdp_enumerator;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add;
+ this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del;
+ this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list;
+ this->public.check_for_hash_and_url = (void(*)(stroke_ca_t*, certificate_t*))check_for_hash_and_url;
+ this->public.destroy = (void(*)(stroke_ca_t*))destroy;
+
+ this->sections = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ this->cred = cred;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_ca.h b/src/libcharon/plugins/stroke/stroke_ca.h
new file mode 100644
index 000000000..21af912ea
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_ca.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * 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 stroke_ca stroke_ca
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_CA_H_
+#define STROKE_CA_H_
+
+#include <stroke_msg.h>
+
+#include "stroke_cred.h"
+
+typedef struct stroke_ca_t stroke_ca_t;
+
+/**
+ * ipsec.conf ca section handling.
+ */
+struct stroke_ca_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Add a CA to the set using a stroke_msg_t.
+ *
+ * @param msg stroke message containing CA info
+ */
+ void (*add)(stroke_ca_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove a CA from the set using a stroke_msg_t.
+ *
+ * @param msg stroke message containing CA info
+ */
+ void (*del)(stroke_ca_t *this, stroke_msg_t *msg);
+
+ /**
+ * List CA sections to stroke console.
+ *
+ * @param msg stroke message
+ */
+ void (*list)(stroke_ca_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Check if a certificate can be made available through hash and URL.
+ *
+ * @param cert peer certificate
+ */
+ void (*check_for_hash_and_url)(stroke_ca_t *this, certificate_t* cert);
+
+ /**
+ * Destroy a stroke_ca instance.
+ */
+ void (*destroy)(stroke_ca_t *this);
+};
+
+/**
+ * Create a stroke_ca instance.
+ */
+stroke_ca_t *stroke_ca_create(stroke_cred_t *cred);
+
+#endif /** STROKE_CA_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
new file mode 100644
index 000000000..bbc1e7a31
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -0,0 +1,949 @@
+/*
+ * 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.
+ */
+
+#include "stroke_config.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <utils/lexparser.h>
+
+typedef struct private_stroke_config_t private_stroke_config_t;
+
+/**
+ * private data of stroke_config
+ */
+struct private_stroke_config_t {
+
+ /**
+ * public functions
+ */
+ stroke_config_t public;
+
+ /**
+ * list of peer_cfg_t
+ */
+ linked_list_t *list;
+
+ /**
+ * mutex to lock config list
+ */
+ mutex_t *mutex;
+
+ /**
+ * ca sections
+ */
+ stroke_ca_t *ca;
+
+ /**
+ * credentials
+ */
+ stroke_cred_t *cred;
+};
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ this->mutex->lock(this->mutex);
+ return enumerator_create_cleaner(this->list->create_enumerator(this->list),
+ (void*)this->mutex->unlock, this->mutex);
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this,
+ host_t *me, host_t *other)
+{
+ this->mutex->lock(this->mutex);
+ return enumerator_create_filter(this->list->create_enumerator(this->list),
+ (void*)ike_filter, this->mutex,
+ (void*)this->mutex->unlock);
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *name)
+{
+ enumerator_t *e1, *e2;
+ peer_cfg_t *current, *found = NULL;
+ child_cfg_t *child;
+
+ this->mutex->lock(this->mutex);
+ e1 = this->list->create_enumerator(this->list);
+ while (e1->enumerate(e1, &current))
+ {
+ /* compare peer_cfgs name first */
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ /* compare all child_cfg names otherwise */
+ e2 = current->create_child_cfg_enumerator(current);
+ while (e2->enumerate(e2, &child))
+ {
+ if (streq(child->get_name(child), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (found)
+ {
+ break;
+ }
+ }
+ e1->destroy(e1);
+ this->mutex->unlock(this->mutex);
+ return found;
+}
+
+/**
+ * parse a proposal string, either into ike_cfg or child_cfg
+ */
+static void add_proposals(private_stroke_config_t *this, char *string,
+ ike_cfg_t *ike_cfg, child_cfg_t *child_cfg)
+{
+ if (string)
+ {
+ char *single;
+ char *strict;
+ proposal_t *proposal;
+ protocol_id_t proto = PROTO_ESP;
+
+ if (ike_cfg)
+ {
+ proto = PROTO_IKE;
+ }
+ strict = string + strlen(string) - 1;
+ if (*strict == '!')
+ {
+ *strict = '\0';
+ }
+ else
+ {
+ strict = NULL;
+ }
+ while ((single = strsep(&string, ",")))
+ {
+ proposal = proposal_create_from_string(proto, single);
+ if (proposal)
+ {
+ if (ike_cfg)
+ {
+ ike_cfg->add_proposal(ike_cfg, proposal);
+ }
+ else
+ {
+ child_cfg->add_proposal(child_cfg, proposal);
+ }
+ continue;
+ }
+ DBG1(DBG_CFG, "skipped invalid proposal string: %s", single);
+ }
+ if (strict)
+ {
+ return;
+ }
+ /* add default porposal to the end if not strict */
+ }
+ if (ike_cfg)
+ {
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ }
+ else
+ {
+ child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ }
+}
+
+/**
+ * Build an IKE config from a stroke message
+ */
+static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
+{
+ stroke_end_t tmp_end;
+ ike_cfg_t *ike_cfg;
+ char *interface;
+ host_t *host;
+
+ host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
+ if (host)
+ {
+ interface = charon->kernel_interface->get_interface(
+ charon->kernel_interface, host);
+ host->destroy(host);
+ if (interface)
+ {
+ DBG2(DBG_CFG, "left is other host, swapping ends");
+ tmp_end = msg->add_conn.me;
+ msg->add_conn.me = msg->add_conn.other;
+ msg->add_conn.other = tmp_end;
+ free(interface);
+ }
+ else
+ {
+ host = host_create_from_dns(msg->add_conn.me.address, 0, 0);
+ if (host)
+ {
+ interface = charon->kernel_interface->get_interface(
+ charon->kernel_interface, host);
+ host->destroy(host);
+ if (!interface)
+ {
+ DBG1(DBG_CFG, "left nor right host is our side, "
+ "assuming left=local");
+ }
+ else
+ {
+ free(interface);
+ }
+
+ }
+ }
+ }
+ ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
+ msg->add_conn.force_encap,
+ msg->add_conn.me.address, msg->add_conn.me.ikeport,
+ msg->add_conn.other.address, msg->add_conn.other.ikeport);
+ add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
+ return ike_cfg;
+}
+
+/**
+ * Add CRL constraint to config
+ */
+static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
+{
+ /* CRL/OCSP policy, for remote config only */
+ if (!local)
+ {
+ switch (policy)
+ {
+ case CRL_STRICT_YES:
+ /* if yes, we require a GOOD validation */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ break;
+ case CRL_STRICT_IFURI:
+ /* for ifuri, a SKIPPED validation is sufficient */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * build authentication config
+ */
+static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg, bool local, bool primary)
+{
+ identification_t *identity;
+ certificate_t *certificate;
+ char *auth, *id, *cert, *ca;
+ stroke_end_t *end, *other_end;
+ auth_cfg_t *cfg;
+ char eap_buf[32];
+
+ /* select strings */
+ if (local)
+ {
+ end = &msg->add_conn.me;
+ other_end = &msg->add_conn.other;
+ }
+ else
+ {
+ end = &msg->add_conn.other;
+ other_end = &msg->add_conn.me;
+ }
+ if (primary)
+ {
+ auth = end->auth;
+ id = end->id;
+ if (!id)
+ { /* leftid/rightid fallback to address */
+ id = end->address;
+ }
+ cert = end->cert;
+ ca = end->ca;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca;
+ }
+ }
+ else
+ {
+ auth = end->auth2;
+ id = end->id2;
+ if (local && !id)
+ { /* leftid2 falls back to leftid */
+ id = end->id;
+ }
+ cert = end->cert2;
+ ca = end->ca2;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca2;
+ }
+ }
+
+ if (!auth)
+ {
+ if (primary)
+ {
+ if (local)
+ { /* "leftauth" not defined, fall back to deprecated "authby" */
+ switch (msg->add_conn.auth_method)
+ {
+ default:
+ case AUTH_CLASS_PUBKEY:
+ auth = "pubkey";
+ break;
+ case AUTH_CLASS_PSK:
+ auth = "psk";
+ break;
+ case AUTH_CLASS_EAP:
+ auth = "eap";
+ break;
+ }
+ }
+ else
+ { /* "rightauth" not defined, fall back to deprecated "eap" */
+ if (msg->add_conn.eap_type)
+ {
+ if (msg->add_conn.eap_vendor)
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
+ msg->add_conn.eap_type,
+ msg->add_conn.eap_vendor);
+ }
+ else
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
+ msg->add_conn.eap_type);
+ }
+ auth = eap_buf;
+ }
+ else
+ { /* not EAP => no constraints for this peer */
+ auth = "any";
+ }
+ }
+ }
+ else
+ { /* no second authentication round, fine */
+ return NULL;
+ }
+ }
+
+ cfg = auth_cfg_create();
+
+ /* add identity and peer certifcate */
+ identity = identification_create_from_string(id);
+ if (cert)
+ {
+ certificate = this->cred->load_peer(this->cred, cert);
+ if (certificate)
+ {
+ if (local)
+ {
+ this->ca->check_for_hash_and_url(this->ca, certificate);
+ }
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ if (identity->get_type(identity) == ID_ANY ||
+ !certificate->has_subject(certificate, identity))
+ {
+ DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, "
+ "defaulting to '%Y'", identity,
+ certificate->get_subject(certificate));
+ identity->destroy(identity);
+ identity = certificate->get_subject(certificate);
+ identity = identity->clone(identity);
+ }
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+
+ /* CA constraint */
+ if (ca)
+ {
+ identity = identification_create_from_string(ca);
+ certificate = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, identity, TRUE);
+ identity->destroy(identity);
+ if (certificate)
+ {
+ cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "CA certificate %s not found, discarding CA "
+ "constraint", ca);
+ }
+ }
+
+ /* AC groups */
+ if (end->groups)
+ {
+ enumerator_t *enumerator;
+ char *group;
+
+ enumerator = enumerator_create_token(end->groups, ",", " ");
+ while (enumerator->enumerate(enumerator, &group))
+ {
+ identity = identification_create_from_encoding(ID_IETF_ATTR_STRING,
+ chunk_create(group, strlen(group)));
+ cfg->add(cfg, AUTH_RULE_AC_GROUP, identity);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* authentication metod (class, actually) */
+ if (streq(auth, "pubkey") ||
+ streq(auth, "rsasig") || streq(auth, "rsa") ||
+ streq(auth, "ecdsasig") || streq(auth, "ecdsa"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ else if (streq(auth, "psk") || streq(auth, "secret"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ }
+ else if (strneq(auth, "eap", 3))
+ {
+ enumerator_t *enumerator;
+ char *str;
+ int i = 0, type = 0, vendor;
+
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+ /* parse EAP string, format: eap[-type[-vendor]] */
+ enumerator = enumerator_create_token(auth, "-", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ switch (i)
+ {
+ case 1:
+ type = eap_type_from_string(str);
+ if (!type)
+ {
+ type = atoi(str);
+ if (!type)
+ {
+ DBG1(DBG_CFG, "unknown EAP method: %s", str);
+ break;
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ break;
+ case 2:
+ if (type)
+ {
+ vendor = atoi(str);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "unknown EAP vendor: %s", str);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ i++;
+ }
+ enumerator->destroy(enumerator);
+
+ if (msg->add_conn.eap_identity)
+ {
+ if (streq(msg->add_conn.eap_identity, "%identity"))
+ {
+ identity = identification_create_from_encoding(ID_ANY,
+ chunk_empty);
+ }
+ else
+ {
+ identity = identification_create_from_string(
+ msg->add_conn.eap_identity);
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
+ }
+ }
+ else
+ {
+ if (!streq(auth, "any"))
+ {
+ DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
+ auth);
+ }
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ return cfg;
+}
+
+/**
+ * build a peer_cfg from a stroke msg
+ */
+static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg, ike_cfg_t *ike_cfg)
+{
+ identification_t *peer_id = NULL;
+ peer_cfg_t *mediated_by = NULL;
+ host_t *vip = NULL;
+ unique_policy_t unique;
+ u_int32_t rekey = 0, reauth = 0, over, jitter;
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth_cfg;
+
+#ifdef ME
+ if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
+ {
+ DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
+ "at the same time, aborting");
+ return NULL;
+ }
+
+ if (msg->add_conn.ikeme.mediation)
+ {
+ /* force unique connections for mediation connections */
+ msg->add_conn.unique = 1;
+ }
+
+ if (msg->add_conn.ikeme.mediated_by)
+ {
+ mediated_by = charon->backends->get_peer_cfg_by_name(charon->backends,
+ msg->add_conn.ikeme.mediated_by);
+ if (!mediated_by)
+ {
+ DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
+ msg->add_conn.ikeme.mediated_by);
+ return NULL;
+ }
+ if (!mediated_by->is_mediation(mediated_by))
+ {
+ DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is "
+ "no mediation connection, aborting",
+ msg->add_conn.ikeme.mediated_by, msg->add_conn.name);
+ mediated_by->destroy(mediated_by);
+ return NULL;
+ }
+ if (msg->add_conn.ikeme.peerid)
+ {
+ peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
+ }
+ else if (msg->add_conn.other.id)
+ {
+ peer_id = identification_create_from_string(msg->add_conn.other.id);
+ }
+ }
+#endif /* ME */
+
+ jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
+ over = msg->add_conn.rekey.margin;
+ if (msg->add_conn.rekey.reauth)
+ {
+ reauth = msg->add_conn.rekey.ike_lifetime - over;
+ }
+ else
+ {
+ rekey = msg->add_conn.rekey.ike_lifetime - over;
+ }
+ if (msg->add_conn.me.sourceip_mask)
+ {
+ if (msg->add_conn.me.sourceip)
+ {
+ vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
+ }
+ if (!vip)
+ { /* if it is set to something like %poolname, request an address */
+ if (msg->add_conn.me.subnets)
+ { /* use the same address as in subnet, if any */
+ if (strchr(msg->add_conn.me.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else
+ {
+ if (strchr(ike_cfg->get_my_addr(ike_cfg), ':'))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET);
+ }
+ }
+ }
+ }
+ switch (msg->add_conn.unique)
+ {
+ case 1: /* yes */
+ case 2: /* replace */
+ unique = UNIQUE_REPLACE;
+ break;
+ case 3: /* keep */
+ unique = UNIQUE_KEEP;
+ break;
+ default: /* no */
+ unique = UNIQUE_NO;
+ break;
+ }
+ if (msg->add_conn.dpd.action == 0)
+ { /* dpdaction=none disables DPD */
+ msg->add_conn.dpd.delay = 0;
+ }
+
+ /* other.sourceip is managed in stroke_attributes. If it is set, we define
+ * the pool name as the connection name, which the attribute provider
+ * uses to serve pool addresses. */
+ peer_cfg = peer_cfg_create(msg->add_conn.name,
+ msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
+ msg->add_conn.me.sendcert, unique,
+ msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
+ msg->add_conn.mobike, msg->add_conn.dpd.delay,
+ vip, msg->add_conn.other.sourceip_mask ?
+ msg->add_conn.name : msg->add_conn.other.sourceip,
+ msg->add_conn.ikeme.mediation, mediated_by, peer_id);
+
+ /* build leftauth= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
+ if (auth_cfg)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+ }
+ else
+ { /* we require at least one config on our side */
+ peer_cfg->destroy(peer_cfg);
+ return NULL;
+ }
+ /* build leftauth2= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
+ if (auth_cfg)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+ }
+ /* build rightauth= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
+ if (auth_cfg)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+ }
+ /* build rightauth2= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
+ if (auth_cfg)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+ }
+ return peer_cfg;
+}
+
+/**
+ * build a traffic selector from a stroke_end
+ */
+static void add_ts(private_stroke_config_t *this,
+ stroke_end_t *end, child_cfg_t *child_cfg, bool local)
+{
+ traffic_selector_t *ts;
+
+ if (end->tohost)
+ {
+ ts = traffic_selector_create_dynamic(end->protocol,
+ end->port ? end->port : 0, end->port ? end->port : 65535);
+ child_cfg->add_traffic_selector(child_cfg, local, ts);
+ }
+ else
+ {
+ host_t *net;
+
+ if (!end->subnets)
+ {
+ net = host_create_from_string(end->address, 0);
+ if (net)
+ {
+ ts = traffic_selector_create_from_subnet(net, 0, end->protocol,
+ end->port);
+ child_cfg->add_traffic_selector(child_cfg, local, ts);
+ }
+ }
+ else
+ {
+ char *del, *start, *bits;
+
+ start = end->subnets;
+ do
+ {
+ int intbits = 0;
+
+ del = strchr(start, ',');
+ if (del)
+ {
+ *del = '\0';
+ }
+ bits = strchr(start, '/');
+ if (bits)
+ {
+ *bits = '\0';
+ intbits = atoi(bits + 1);
+ }
+
+ net = host_create_from_string(start, 0);
+ if (net)
+ {
+ ts = traffic_selector_create_from_subnet(net, intbits,
+ end->protocol, end->port);
+ child_cfg->add_traffic_selector(child_cfg, local, ts);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid subnet: %s, skipped", start);
+ }
+ start = del + 1;
+ }
+ while (del);
+ }
+ }
+}
+
+/**
+ * build a child config from the stroke message
+ */
+static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg)
+{
+ child_cfg_t *child_cfg;
+ action_t dpd;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = msg->add_conn.rekey.ipsec_lifetime,
+ .rekey = msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
+ .jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100
+ },
+ .bytes = {
+ .life = msg->add_conn.rekey.life_bytes,
+ .rekey = msg->add_conn.rekey.life_bytes - msg->add_conn.rekey.margin_bytes,
+ .jitter = msg->add_conn.rekey.margin_bytes * msg->add_conn.rekey.fuzz / 100
+ },
+ .packets = {
+ .life = msg->add_conn.rekey.life_packets,
+ .rekey = msg->add_conn.rekey.life_packets - msg->add_conn.rekey.margin_packets,
+ .jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
+ }
+ };
+
+ switch (msg->add_conn.dpd.action)
+ { /* map startes magic values to our action type */
+ case 2: /* =hold */
+ dpd = ACTION_ROUTE;
+ break;
+ case 3: /* =restart */
+ dpd = ACTION_RESTART;
+ break;
+ default:
+ dpd = ACTION_NONE;
+ break;
+ }
+
+ child_cfg = child_cfg_create(
+ msg->add_conn.name, &lifetime,
+ msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
+ msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp,
+ msg->add_conn.inactivity);
+ child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
+ msg->add_conn.install_policy);
+ add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
+ add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
+
+ add_proposals(this, msg->add_conn.algorithms.esp, NULL, child_cfg);
+
+ return child_cfg;
+}
+
+/**
+ * Implementation of stroke_config_t.add.
+ */
+static void add(private_stroke_config_t *this, stroke_msg_t *msg)
+{
+ ike_cfg_t *ike_cfg, *existing_ike;
+ peer_cfg_t *peer_cfg, *existing;
+ child_cfg_t *child_cfg;
+ enumerator_t *enumerator;
+ bool use_existing = FALSE;
+
+ ike_cfg = build_ike_cfg(this, msg);
+ if (!ike_cfg)
+ {
+ return;
+ }
+ peer_cfg = build_peer_cfg(this, msg, ike_cfg);
+ if (!peer_cfg)
+ {
+ ike_cfg->destroy(ike_cfg);
+ return;
+ }
+
+ enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &existing))
+ {
+ existing_ike = existing->get_ike_cfg(existing);
+ if (existing->equals(existing, peer_cfg) &&
+ existing_ike->equals(existing_ike, peer_cfg->get_ike_cfg(peer_cfg)))
+ {
+ use_existing = TRUE;
+ peer_cfg->destroy(peer_cfg);
+ peer_cfg = existing;
+ peer_cfg->get_ref(peer_cfg);
+ DBG1(DBG_CFG, "added child to existing configuration '%s'",
+ peer_cfg->get_name(peer_cfg));
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ child_cfg = build_child_cfg(this, msg);
+ if (!child_cfg)
+ {
+ peer_cfg->destroy(peer_cfg);
+ return;
+ }
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+
+ if (use_existing)
+ {
+ peer_cfg->destroy(peer_cfg);
+ }
+ else
+ {
+ /* add config to backend */
+ DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
+ this->mutex->lock(this->mutex);
+ this->list->insert_last(this->list, peer_cfg);
+ this->mutex->unlock(this->mutex);
+ }
+}
+
+/**
+ * Implementation of stroke_config_t.del.
+ */
+static void del(private_stroke_config_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator, *children;
+ peer_cfg_t *peer;
+ child_cfg_t *child;
+ bool deleted = FALSE;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
+ {
+ bool keep = FALSE;
+
+ /* remove any child with such a name */
+ children = peer->create_child_cfg_enumerator(peer);
+ while (children->enumerate(children, &child))
+ {
+ if (streq(child->get_name(child), msg->del_conn.name))
+ {
+ peer->remove_child_cfg(peer, children);
+ child->destroy(child);
+ deleted = TRUE;
+ }
+ else
+ {
+ keep = TRUE;
+ }
+ }
+ children->destroy(children);
+
+ /* if peer config matches, or has no children anymore, remove it */
+ if (!keep || streq(peer->get_name(peer), msg->del_conn.name))
+ {
+ this->list->remove_at(this->list, enumerator);
+ peer->destroy(peer);
+ deleted = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (deleted)
+ {
+ DBG1(DBG_CFG, "deleted connection '%s'", msg->del_conn.name);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "connection '%s' not found", msg->del_conn.name);
+ }
+}
+
+/**
+ * Implementation of stroke_config_t.destroy
+ */
+static void destroy(private_stroke_config_t *this)
+{
+ this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy));
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
+{
+ private_stroke_config_t *this = malloc_thing(private_stroke_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.add = (void(*)(stroke_config_t*, stroke_msg_t *msg))add;
+ this->public.del = (void(*)(stroke_config_t*, stroke_msg_t *msg))del;
+ this->public.destroy = (void(*)(stroke_config_t*))destroy;
+
+ this->list = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+ this->ca = ca;
+ this->cred = cred;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
new file mode 100644
index 000000000..05e4665ca
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -0,0 +1,66 @@
+/*
+ * 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 stroke_config stroke_config
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_CONFIG_H_
+#define STROKE_CONFIG_H_
+
+#include <config/backend.h>
+#include <stroke_msg.h>
+#include "stroke_ca.h"
+#include "stroke_cred.h"
+
+typedef struct stroke_config_t stroke_config_t;
+
+/**
+ * Stroke in-memory configuration backend
+ */
+struct stroke_config_t {
+
+ /**
+ * Implements the backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Add a configuration to the backend.
+ *
+ * @param msg received stroke message containing config
+ */
+ void (*add)(stroke_config_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove a configuration from the backend.
+ *
+ * @param msg received stroke message containing config name
+ */
+ void (*del)(stroke_config_t *this, stroke_msg_t *msg);
+
+ /**
+ * Destroy a stroke_config instance.
+ */
+ void (*destroy)(stroke_config_t *this);
+};
+
+/**
+ * Create a stroke_config instance.
+ */
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred);
+
+#endif /** STROKE_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
new file mode 100644
index 000000000..a03aef697
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -0,0 +1,491 @@
+/*
+ * 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.
+ */
+
+#include "stroke_control.h"
+
+#include <daemon.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+typedef struct private_stroke_control_t private_stroke_control_t;
+
+/**
+ * private data of stroke_control
+ */
+struct private_stroke_control_t {
+
+ /**
+ * public functions
+ */
+ stroke_control_t public;
+};
+
+
+typedef struct stroke_log_info_t stroke_log_info_t;
+
+/**
+ * helper struct to say what and where to log when using controller callback
+ */
+struct stroke_log_info_t {
+
+ /**
+ * level to log up to
+ */
+ level_t level;
+
+ /**
+ * where to write log
+ */
+ FILE* out;
+};
+
+/**
+ * logging to the stroke interface
+ */
+static bool stroke_log(stroke_log_info_t *info, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args)
+{
+ if (level <= info->level)
+ {
+ if (vfprintf(info->out, format, args) < 0 ||
+ fprintf(info->out, "\n") < 0 ||
+ fflush(info->out) != 0)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * get the child_cfg with the same name as the 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;
+}
+
+/**
+ * Implementation of stroke_control_t.initiate.
+ */
+static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ stroke_log_info_t info;
+
+ peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
+ msg->initiate.name);
+ if (peer_cfg == NULL)
+ {
+ DBG1(DBG_CFG, "no config named '%s'\n", msg->initiate.name);
+ return;
+ }
+ if (peer_cfg->get_ike_version(peer_cfg) != 2)
+ {
+ DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
+ peer_cfg->get_ike_version(peer_cfg));
+ peer_cfg->destroy(peer_cfg);
+ return;
+ }
+
+ child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
+ if (child_cfg == NULL)
+ {
+ DBG1(DBG_CFG, "no child config named '%s'\n", msg->initiate.name);
+ peer_cfg->destroy(peer_cfg);
+ return;
+ }
+
+ if (msg->output_verbosity < 0)
+ {
+ charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
+ NULL, NULL);
+ }
+ else
+ {
+ info.out = out;
+ info.level = msg->output_verbosity;
+ charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
+ (controller_cb_t)stroke_log, &info);
+ }
+}
+
+/**
+ * Implementation of stroke_control_t.terminate.
+ */
+static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ char *string, *pos = NULL, *name = NULL;
+ u_int32_t id = 0;
+ bool child, all = FALSE;
+ int len;
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ linked_list_t *ike_list, *child_list;
+ stroke_log_info_t info;
+ uintptr_t del;
+
+ string = msg->terminate.name;
+
+ len = strlen(string);
+ if (len < 1)
+ {
+ DBG1(DBG_CFG, "error parsing string");
+ return;
+ }
+ switch (string[len-1])
+ {
+ case '}':
+ child = TRUE;
+ pos = strchr(string, '{');
+ break;
+ case ']':
+ child = FALSE;
+ pos = strchr(string, '[');
+ break;
+ default:
+ name = string;
+ child = FALSE;
+ break;
+ }
+
+ if (name)
+ {
+ /* is a single name */
+ }
+ else if (pos == string + len - 2)
+ { /* is name[] or name{} */
+ string[len-2] = '\0';
+ name = string;
+ }
+ else
+ {
+ if (*(pos + 1) == '*')
+ { /* is name[*] */
+ all = TRUE;
+ *pos = '\0';
+ name = string;
+ }
+ else
+ { /* is name[123] or name{23} */
+ id = atoi(pos + 1);
+ if (id == 0)
+ {
+ DBG1(DBG_CFG, "error parsing string");
+ return;
+ }
+ }
+ }
+
+ info.out = out;
+ info.level = msg->output_verbosity;
+
+ if (id)
+ {
+ if (child)
+ {
+ charon->controller->terminate_child(charon->controller, id,
+ (controller_cb_t)stroke_log, &info);
+ }
+ else
+ {
+ charon->controller->terminate_ike(charon->controller, id,
+ (controller_cb_t)stroke_log, &info);
+ }
+ return;
+ }
+
+ ike_list = linked_list_create();
+ child_list = linked_list_create();
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ child_sa_t *child_sa;
+ iterator_t *children;
+
+ if (child)
+ {
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (streq(name, child_sa->get_name(child_sa)))
+ {
+ child_list->insert_last(child_list,
+ (void*)(uintptr_t)child_sa->get_reqid(child_sa));
+ if (!all)
+ {
+ break;
+ }
+ }
+ }
+ children->destroy(children);
+ if (child_list->get_count(child_list) && !all)
+ {
+ break;
+ }
+ }
+ else if (streq(name, ike_sa->get_name(ike_sa)))
+ {
+ ike_list->insert_last(ike_list,
+ (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa));
+ if (!all)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = child_list->create_enumerator(child_list);
+ while (enumerator->enumerate(enumerator, &del))
+ {
+ charon->controller->terminate_child(charon->controller, del,
+ (controller_cb_t)stroke_log, &info);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = ike_list->create_enumerator(ike_list);
+ while (enumerator->enumerate(enumerator, &del))
+ {
+ charon->controller->terminate_ike(charon->controller, del,
+ (controller_cb_t)stroke_log, &info);
+ }
+ enumerator->destroy(enumerator);
+
+ if (child_list->get_count(child_list) == 0 &&
+ ike_list->get_count(ike_list) == 0)
+ {
+ DBG1(DBG_CFG, "no %s_SA named '%s' found",
+ child ? "CHILD" : "IKE", name);
+ }
+ ike_list->destroy(ike_list);
+ child_list->destroy(child_list);
+}
+
+/**
+ * Implementation of stroke_control_t.terminate_srcip.
+ */
+static void terminate_srcip(private_stroke_control_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ host_t *start = NULL, *end = NULL, *vip;
+ chunk_t chunk_start, chunk_end = chunk_empty, chunk_vip;
+
+ if (msg->terminate_srcip.start)
+ {
+ start = host_create_from_string(msg->terminate_srcip.start, 0);
+ }
+ if (!start)
+ {
+ DBG1(DBG_CFG, "invalid start address: %s", msg->terminate_srcip.start);
+ return;
+ }
+ chunk_start = start->get_address(start);
+ if (msg->terminate_srcip.end)
+ {
+ end = host_create_from_string(msg->terminate_srcip.end, 0);
+ if (!end)
+ {
+ DBG1(DBG_CFG, "invalid end address: %s", msg->terminate_srcip.end);
+ start->destroy(start);
+ return;
+ }
+ chunk_end = end->get_address(end);
+ }
+
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (!vip)
+ {
+ continue;
+ }
+ if (!end)
+ {
+ if (!vip->ip_equals(vip, start))
+ {
+ continue;
+ }
+ }
+ else
+ {
+ chunk_vip = vip->get_address(vip);
+ if (chunk_vip.len != chunk_start.len ||
+ chunk_vip.len != chunk_end.len ||
+ memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 ||
+ memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0)
+ {
+ continue;
+ }
+ }
+
+ /* schedule delete asynchronously */
+ charon->processor->queue_job(charon->processor, (job_t*)
+ delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+ }
+ enumerator->destroy(enumerator);
+ start->destroy(start);
+ DESTROY_IF(end);
+}
+
+/**
+ * Implementation of stroke_control_t.purge_ike
+ */
+static void purge_ike(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ enumerator_t *enumerator;
+ iterator_t *iterator;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ linked_list_t *list;
+ uintptr_t del;
+ stroke_log_info_t info;
+
+ info.out = out;
+ info.level = msg->output_verbosity;
+
+ list = linked_list_create();
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ if (!iterator->iterate(iterator, (void**)&child_sa))
+ {
+ list->insert_last(list,
+ (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa));
+ }
+ iterator->destroy(iterator);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &del))
+ {
+ charon->controller->terminate_ike(charon->controller, del,
+ (controller_cb_t)stroke_log, &info);
+ }
+ enumerator->destroy(enumerator);
+ list->destroy(list);
+}
+
+/**
+ * Implementation of stroke_control_t.route.
+ */
+static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+
+ peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
+ msg->route.name);
+ if (peer_cfg == NULL)
+ {
+ fprintf(out, "no config named '%s'\n", msg->route.name);
+ return;
+ }
+ if (peer_cfg->get_ike_version(peer_cfg) != 2)
+ {
+ peer_cfg->destroy(peer_cfg);
+ return;
+ }
+
+ child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
+ if (child_cfg == NULL)
+ {
+ fprintf(out, "no child config named '%s'\n", msg->route.name);
+ peer_cfg->destroy(peer_cfg);
+ return;
+ }
+
+ if (charon->traps->install(charon->traps, peer_cfg, child_cfg))
+ {
+ fprintf(out, "configuration '%s' routed\n", msg->route.name);
+ }
+ else
+ {
+ fprintf(out, "routing configuration '%s' failed\n", msg->route.name);
+ }
+ peer_cfg->destroy(peer_cfg);
+ child_cfg->destroy(child_cfg);
+}
+
+/**
+ * Implementation of stroke_control_t.unroute.
+ */
+static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ child_sa_t *child_sa;
+ enumerator_t *enumerator;
+ u_int32_t id;
+
+ enumerator = charon->traps->create_enumerator(charon->traps);
+ while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ {
+ if (streq(msg->unroute.name, child_sa->get_name(child_sa)))
+ {
+ id = child_sa->get_reqid(child_sa);
+ enumerator->destroy(enumerator);
+ charon->traps->uninstall(charon->traps, id);
+ fprintf(out, "configuration '%s' unrouted\n", msg->unroute.name);
+ return;
+ }
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "configuration '%s' not found\n", msg->unroute.name);
+}
+
+/**
+ * Implementation of stroke_control_t.destroy
+ */
+static void destroy(private_stroke_control_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_control_t *stroke_control_create()
+{
+ private_stroke_control_t *this = malloc_thing(private_stroke_control_t);
+
+ this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate;
+ this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate;
+ this->public.terminate_srcip = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate_srcip;
+ this->public.purge_ike = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))purge_ike;
+ this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route;
+ this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute;
+ this->public.destroy = (void(*)(stroke_control_t*))destroy;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_control.h b/src/libcharon/plugins/stroke/stroke_control.h
new file mode 100644
index 000000000..9b49bdc31
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_control.h
@@ -0,0 +1,88 @@
+/*
+ * 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 stroke_control stroke_control
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_CONTROL_H_
+#define STROKE_CONTROL_H_
+
+#include <stroke_msg.h>
+#include <library.h>
+#include <stdio.h>
+
+typedef struct stroke_control_t stroke_control_t;
+
+/**
+ * Process stroke control messages
+ */
+struct stroke_control_t {
+
+ /**
+ * Initiate a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*initiate)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Terminate a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*terminate)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Terminate a connection by peers virtual IP.
+ *
+ * @param msg stroke message
+ */
+ void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Delete IKE_SAs without a CHILD_SA.
+ *
+ * @param msg stroke message
+ */
+ void (*purge_ike)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Route a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*route)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Unroute a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*unroute)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Destroy a stroke_control instance.
+ */
+ void (*destroy)(stroke_control_t *this);
+};
+
+/**
+ * Create a stroke_control instance.
+ */
+stroke_control_t *stroke_control_create();
+
+#endif /** STROKE_CONTROL_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
new file mode 100644
index 000000000..e0a5210a9
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * 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/stat.h>
+#include <limits.h>
+#include <glob.h>
+#include <libgen.h>
+
+#include "stroke_cred.h"
+#include "stroke_shared_key.h"
+
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/ac.h>
+#include <utils/linked_list.h>
+#include <utils/lexparser.h>
+#include <threading/rwlock.h>
+#include <daemon.h>
+
+/* configuration directories and files */
+#define CONFIG_DIR IPSEC_CONFDIR
+#define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
+#define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
+#define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
+#define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
+#define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
+#define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
+#define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
+#define CRL_DIR IPSEC_D_DIR "/crls"
+#define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
+
+#define MAX_SECRETS_RECURSION 10
+
+typedef struct private_stroke_cred_t private_stroke_cred_t;
+
+/**
+ * private data of stroke_cred
+ */
+struct private_stroke_cred_t {
+
+ /**
+ * public functions
+ */
+ stroke_cred_t public;
+
+ /**
+ * list of trusted peer/signer/CA certificates (certificate_t)
+ */
+ linked_list_t *certs;
+
+ /**
+ * list of shared secrets (private_shared_key_t)
+ */
+ linked_list_t *shared;
+
+ /**
+ * list of private keys (private_key_t)
+ */
+ linked_list_t *private;
+
+ /**
+ * read-write lock to lists
+ */
+ rwlock_t *lock;
+
+ /**
+ * cache CRLs to disk?
+ */
+ bool cachecrl;
+};
+
+/**
+ * data to pass to various filters
+ */
+typedef struct {
+ private_stroke_cred_t *this;
+ identification_t *id;
+ certificate_type_t type;
+} id_data_t;
+
+/**
+ * destroy id enumerator data and unlock list
+ */
+static void id_data_destroy(id_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * filter function for private key enumerator
+ */
+static bool private_filter(id_data_t *data,
+ private_key_t **in, private_key_t **out)
+{
+ private_key_t *key;
+
+ key = *in;
+ if (data->id == NULL)
+ {
+ *out = key;
+ return TRUE;
+ }
+ if (key->has_fingerprint(key, data->id->get_encoding(data->id)))
+ {
+ *out = key;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implements credential_set_t.create_private_enumerator
+ */
+static enumerator_t* create_private_enumerator(private_stroke_cred_t *this,
+ key_type_t type, identification_t *id)
+{
+ id_data_t *data;
+
+ data = malloc_thing(id_data_t);
+ data->this = this;
+ data->id = id;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->private->create_enumerator(this->private),
+ (void*)private_filter, data,
+ (void*)id_data_destroy);
+}
+
+/**
+ * filter function for certs enumerator
+ */
+static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out)
+{
+ public_key_t *public;
+ certificate_t *cert = *in;
+
+ if (data->type != CERT_ANY && data->type != cert->get_type(cert))
+ {
+ return FALSE;
+ }
+ if (data->id == NULL || cert->has_subject(cert, data->id))
+ {
+ *out = *in;
+ return TRUE;
+ }
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ if (public->has_fingerprint(public, data->id->get_encoding(data->id)))
+ {
+ public->destroy(public);
+ *out = *in;
+ return TRUE;
+ }
+ public->destroy(public);
+ }
+ return FALSE;
+}
+
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ id_data_t *data;
+
+ if (trusted && (cert == CERT_X509_CRL || cert == CERT_X509_AC))
+ {
+ return NULL;
+ }
+ data = malloc_thing(id_data_t);
+ data->this = this;
+ data->id = id;
+ data->type = cert;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->certs->create_enumerator(this->certs),
+ (void*)certs_filter, data,
+ (void*)id_data_destroy);
+}
+
+typedef struct {
+ private_stroke_cred_t *this;
+ identification_t *me;
+ identification_t *other;
+ shared_key_type_t type;
+} shared_data_t;
+
+/**
+ * free shared key enumerator data and unlock list
+ */
+static void shared_data_destroy(shared_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * filter function for certs enumerator
+ */
+static bool shared_filter(shared_data_t *data,
+ stroke_shared_key_t **in, shared_key_t **out,
+ void **unused1, id_match_t *me,
+ void **unused2, id_match_t *other)
+{
+ id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
+ stroke_shared_key_t *stroke = *in;
+ shared_key_t *shared = &stroke->shared;
+
+ if (data->type != SHARED_ANY && shared->get_type(shared) != data->type)
+ {
+ return FALSE;
+ }
+
+ if (data->me)
+ {
+ my_match = stroke->has_owner(stroke, data->me);
+ }
+ if (data->other)
+ {
+ other_match = stroke->has_owner(stroke, data->other);
+ }
+ if ((data->me || data->other) && (!my_match && !other_match))
+ {
+ return FALSE;
+ }
+ *out = shared;
+ if (me)
+ {
+ *me = my_match;
+ }
+ if (other)
+ {
+ *other = other_match;
+ }
+ return TRUE;
+}
+
+/**
+ * Implements credential_set_t.create_shared_enumerator
+ */
+static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this,
+ shared_key_type_t type, identification_t *me,
+ identification_t *other)
+{
+ shared_data_t *data = malloc_thing(shared_data_t);
+
+ data->this = this;
+ data->me = me;
+ data->other = other;
+ data->type = type;
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->shared->create_enumerator(this->shared),
+ (void*)shared_filter, data,
+ (void*)shared_data_destroy);
+}
+
+/**
+ * Add a certificate to chain
+ */
+static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
+{
+ certificate_t *current;
+ enumerator_t *enumerator;
+ bool new = TRUE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->certs->create_enumerator(this->certs);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->equals(current, cert))
+ {
+ /* cert already in queue */
+ cert->destroy(cert);
+ cert = current;
+ new = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (new)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+ this->lock->unlock(this->lock);
+ return cert;
+}
+
+/**
+ * Implementation of stroke_cred_t.load_ca.
+ */
+static certificate_t* load_ca(private_stroke_cred_t *this, char *filename)
+{
+ certificate_t *cert;
+ char path[PATH_MAX];
+
+ if (*filename == '/')
+ {
+ snprintf(path, sizeof(path), "%s", filename);
+ }
+ else
+ {
+ snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
+ }
+
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, path,
+ BUILD_END);
+ if (cert)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ DBG1(DBG_CFG, " ca certificate \"%Y\" misses ca basic constraint, "
+ "discarded", cert->get_subject(cert));
+ cert->destroy(cert);
+ return NULL;
+ }
+ return (certificate_t*)add_cert(this, cert);
+ }
+ return NULL;
+}
+
+/**
+ * Add X.509 CRL to chain
+ */
+static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
+{
+ certificate_t *current, *cert = &crl->certificate;
+ enumerator_t *enumerator;
+ bool new = TRUE, found = FALSE;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->certs->create_enumerator(this->certs);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->get_type(current) == CERT_X509_CRL)
+ {
+ crl_t *crl_c = (crl_t*)current;
+ chunk_t authkey = crl->get_authKeyIdentifier(crl);
+ chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c);
+
+ /* if compare authorityKeyIdentifiers if available */
+ if (authkey.ptr && authkey_c.ptr && chunk_equals(authkey, authkey_c))
+ {
+ found = TRUE;
+ }
+ else
+ {
+ identification_t *issuer = cert->get_issuer(cert);
+ identification_t *issuer_c = current->get_issuer(current);
+
+ /* otherwise compare issuer distinguished names */
+ if (issuer->equals(issuer, issuer_c))
+ {
+ found = TRUE;
+ }
+ }
+ if (found)
+ {
+ new = cert->is_newer(cert, current);
+ if (new)
+ {
+ this->certs->remove_at(this->certs, enumerator);
+ }
+ else
+ {
+ cert->destroy(cert);
+ }
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (new)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+ this->lock->unlock(this->lock);
+ return new;
+}
+
+/**
+ * Add X.509 attribute certificate to chain
+ */
+static bool add_ac(private_stroke_cred_t *this, ac_t* ac)
+{
+ certificate_t *cert = &ac->certificate;
+
+ this->lock->write_lock(this->lock);
+ this->certs->insert_last(this->certs, cert);
+ this->lock->unlock(this->lock);
+ return TRUE;
+}
+
+/**
+ * Implementation of stroke_cred_t.load_peer.
+ */
+static certificate_t* load_peer(private_stroke_cred_t *this, char *filename)
+{
+ certificate_t *cert;
+ char path[PATH_MAX];
+
+ if (*filename == '/')
+ {
+ snprintf(path, sizeof(path), "%s", filename);
+ }
+ else
+ {
+ snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
+ }
+
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_ANY,
+ BUILD_FROM_FILE, path,
+ BUILD_END);
+ if (cert)
+ {
+ cert = add_cert(this, cert);
+ DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), filename);
+ return cert->get_ref(cert);
+ }
+ DBG1(DBG_CFG, " loading certificate from '%s' failed", filename);
+ return NULL;
+}
+
+/**
+ * load trusted certificates from a directory
+ */
+static void load_certdir(private_stroke_cred_t *this, char *path,
+ certificate_type_t type, x509_flag_t flag)
+{
+ struct stat st;
+ char *file;
+
+ enumerator_t *enumerator = enumerator_create_directory(path);
+
+ if (!enumerator)
+ {
+ DBG1(DBG_CFG, " reading directory failed");
+ return;
+ }
+
+ while (enumerator->enumerate(enumerator, NULL, &file, &st))
+ {
+ certificate_t *cert;
+
+ if (!S_ISREG(st.st_mode))
+ {
+ /* skip special file */
+ continue;
+ }
+ switch (type)
+ {
+ case CERT_X509:
+ if (flag & X509_CA)
+ { /* for CA certificates, we strictly require
+ * the CA basic constraint to be set */
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file, BUILD_END);
+ if (cert)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ DBG1(DBG_CFG, " ca certificate \"%Y\" lacks "
+ "ca basic constraint, discarded",
+ cert->get_subject(cert));
+ cert->destroy(cert);
+ cert = NULL;
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), file);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loading ca certificate from '%s' "
+ "failed", file);
+ }
+ }
+ else
+ { /* for all other flags, we add them to the certificate. */
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file,
+ BUILD_X509_FLAG, flag, BUILD_END);
+ if (cert)
+ {
+ DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), file);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loading certificate from '%s' "
+ "failed", file);
+ }
+ }
+ if (cert)
+ {
+ add_cert(this, cert);
+ }
+ break;
+ case CERT_X509_CRL:
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_FROM_FILE, file,
+ BUILD_END);
+ if (cert)
+ {
+ add_crl(this, (crl_t*)cert);
+ DBG1(DBG_CFG, " loaded crl from '%s'", file);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loading crl from '%s' failed", file);
+ }
+ break;
+ case CERT_X509_AC:
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_AC,
+ BUILD_FROM_FILE, file,
+ BUILD_END);
+ if (cert)
+ {
+ add_ac(this, (ac_t*)cert);
+ DBG1(DBG_CFG, " loaded attribute certificate from '%s'",
+ file);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loading attribute certificate from '%s' "
+ "failed", file);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of credential_set_t.cache_cert.
+ */
+static void cache_cert(private_stroke_cred_t *this, certificate_t *cert)
+{
+ if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl)
+ {
+ /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */
+ crl_t *crl = (crl_t*)cert;
+
+ cert->get_ref(cert);
+ if (add_crl(this, crl))
+ {
+ char buf[BUF_LEN];
+ chunk_t chunk, hex;
+
+ chunk = crl->get_authKeyIdentifier(crl);
+ hex = chunk_to_hex(chunk, NULL, FALSE);
+ snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex);
+ free(hex.ptr);
+
+ chunk = cert->get_encoding(cert);
+ chunk_write(chunk, buf, "crl", 022, TRUE);
+ free(chunk.ptr);
+ }
+ }
+}
+
+/**
+ * Implementation of stroke_cred_t.cachecrl.
+ */
+static void cachecrl(private_stroke_cred_t *this, bool enabled)
+{
+ DBG1(DBG_CFG, "crl caching to %s %s",
+ CRL_DIR, enabled ? "enabled" : "disabled");
+ this->cachecrl = enabled;
+}
+
+
+/**
+ * Convert a string of characters into a binary secret
+ * A string between single or double quotes is treated as ASCII characters
+ * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
+ */
+static err_t extract_secret(chunk_t *secret, chunk_t *line)
+{
+ chunk_t raw_secret;
+ char delimiter = ' ';
+ bool quotes = FALSE;
+
+ if (!eat_whitespace(line))
+ {
+ return "missing secret";
+ }
+
+ if (*line->ptr == '\'' || *line->ptr == '"')
+ {
+ quotes = TRUE;
+ delimiter = *line->ptr;
+ line->ptr++; line->len--;
+ }
+
+ if (!extract_token(&raw_secret, delimiter, line))
+ {
+ if (delimiter == ' ')
+ {
+ raw_secret = *line;
+ }
+ else
+ {
+ return "missing second delimiter";
+ }
+ }
+
+ if (quotes)
+ {
+ /* treat as an ASCII string */
+ *secret = chunk_clone(raw_secret);
+ return NULL;
+ }
+ /* treat 0x as hex, 0s as base64 */
+ if (raw_secret.len > 2)
+ {
+ if (strncasecmp("0x", raw_secret.ptr, 2) == 0)
+ {
+ *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL);
+ return NULL;
+ }
+ if (strncasecmp("0s", raw_secret.ptr, 2) == 0)
+ {
+ *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL);
+ return NULL;
+ }
+ }
+ *secret = chunk_clone(raw_secret);
+ return NULL;
+}
+
+/**
+ * Data to pass to passphrase_cb
+ */
+typedef struct {
+ /** socket we use for prompting */
+ FILE *prompt;
+ /** private key file */
+ char *file;
+ /** buffer for passphrase */
+ char buf[256];
+} passphrase_cb_data_t;
+
+/**
+ * Passphrase callback to read from whack fd
+ */
+chunk_t passphrase_cb(passphrase_cb_data_t *data, int try)
+{
+ chunk_t secret = chunk_empty;;
+
+ if (try > 5)
+ {
+ fprintf(data->prompt, "invalid passphrase, too many trials\n");
+ return chunk_empty;
+ }
+ if (try == 1)
+ {
+ fprintf(data->prompt, "Private key '%s' is encrypted\n", data->file);
+ }
+ else
+ {
+ fprintf(data->prompt, "invalid passphrase\n");
+ }
+ fprintf(data->prompt, "Passphrase:\n");
+ if (fgets(data->buf, sizeof(data->buf), data->prompt))
+ {
+ secret = chunk_create(data->buf, strlen(data->buf));
+ if (secret.len)
+ { /* trim appended \n */
+ secret.len--;
+ }
+ }
+ return secret;
+}
+
+/**
+ * reload ipsec.secrets
+ */
+static void load_secrets(private_stroke_cred_t *this, char *file, int level,
+ FILE *prompt)
+{
+ size_t bytes;
+ int line_nr = 0;
+ chunk_t chunk, src, line;
+ FILE *fd;
+ private_key_t *private;
+ shared_key_t *shared;
+
+ DBG1(DBG_CFG, "loading secrets from '%s'", file);
+
+ fd = fopen(file, "r");
+ if (fd == NULL)
+ {
+ DBG1(DBG_CFG, "opening secrets file '%s' failed", file);
+ return;
+ }
+
+ /* TODO: do error checks */
+ fseek(fd, 0, SEEK_END);
+ chunk.len = ftell(fd);
+ rewind(fd);
+ chunk.ptr = malloc(chunk.len);
+ bytes = fread(chunk.ptr, 1, chunk.len, fd);
+ fclose(fd);
+ src = chunk;
+
+ if (level == 0)
+ {
+ this->lock->write_lock(this->lock);
+
+ /* flush secrets on non-recursive invocation */
+ while (this->shared->remove_last(this->shared,
+ (void**)&shared) == SUCCESS)
+ {
+ shared->destroy(shared);
+ }
+ while (this->private->remove_last(this->private,
+ (void**)&private) == SUCCESS)
+ {
+ private->destroy(private);
+ }
+ }
+
+ while (fetchline(&src, &line))
+ {
+ chunk_t ids, token;
+ shared_key_type_t type;
+
+ line_nr++;
+
+ if (!eat_whitespace(&line))
+ {
+ continue;
+ }
+ if (line.len > strlen("include ") &&
+ strneq(line.ptr, "include ", strlen("include ")))
+ {
+ glob_t buf;
+ char **expanded, *dir, pattern[PATH_MAX];
+ u_char *pos;
+
+ if (level > MAX_SECRETS_RECURSION)
+ {
+ DBG1(DBG_CFG, "maximum level of %d includes reached, ignored",
+ MAX_SECRETS_RECURSION);
+ continue;
+ }
+ /* terminate filename by space */
+ line = chunk_skip(line, strlen("include "));
+ pos = memchr(line.ptr, ' ', line.len);
+ if (pos)
+ {
+ line.len = pos - line.ptr;
+ }
+ if (line.len && line.ptr[0] == '/')
+ {
+ if (line.len + 1 > sizeof(pattern))
+ {
+ DBG1(DBG_CFG, "include pattern too long, ignored");
+ continue;
+ }
+ snprintf(pattern, sizeof(pattern), "%.*s", line.len, line.ptr);
+ }
+ else
+ { /* use directory of current file if relative */
+ dir = strdup(file);
+ dir = dirname(dir);
+
+ if (line.len + 1 + strlen(dir) + 1 > sizeof(pattern))
+ {
+ DBG1(DBG_CFG, "include pattern too long, ignored");
+ free(dir);
+ continue;
+ }
+ snprintf(pattern, sizeof(pattern), "%s/%.*s",
+ dir, line.len, line.ptr);
+ free(dir);
+ }
+ if (glob(pattern, GLOB_ERR, NULL, &buf) != 0)
+ {
+ DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern);
+ globfree(&buf);
+ }
+ else
+ {
+ for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
+ {
+ load_secrets(this, *expanded, level + 1, prompt);
+ }
+ }
+ globfree(&buf);
+ continue;
+ }
+
+ if (line.len > 2 && strneq(": ", line.ptr, 2))
+ {
+ /* no ids, skip the ':' */
+ ids = chunk_empty;
+ line.ptr++;
+ line.len--;
+ }
+ else if (extract_token_str(&ids, " : ", &line))
+ {
+ /* NULL terminate the extracted id string */
+ *(ids.ptr + ids.len) = '\0';
+ }
+ else
+ {
+ DBG1(DBG_CFG, "line %d: missing ' : ' separator", line_nr);
+ goto error;
+ }
+
+ if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
+ {
+ DBG1(DBG_CFG, "line %d: missing token", line_nr);
+ goto error;
+ }
+ if (match("RSA", &token) || match("ECDSA", &token))
+ {
+ char path[PATH_MAX];
+ chunk_t filename;
+ chunk_t secret = chunk_empty;
+ private_key_t *key = NULL;
+ key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
+
+ err_t ugh = extract_value(&filename, &line);
+
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
+ goto error;
+ }
+ if (filename.len == 0)
+ {
+ DBG1(DBG_CFG, "line %d: empty filename", line_nr);
+ goto error;
+ }
+ if (*filename.ptr == '/')
+ {
+ /* absolute path name */
+ snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
+ }
+ else
+ {
+ /* relative path name */
+ snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
+ filename.len, filename.ptr);
+ }
+
+ /* check for optional passphrase */
+ if (eat_whitespace(&line))
+ {
+ ugh = extract_secret(&secret, &line);
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
+ goto error;
+ }
+ }
+ if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7))
+ {
+ if (prompt)
+ {
+ passphrase_cb_data_t data;
+
+ data.prompt = prompt;
+ data.file = path;
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ key_type, BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE_CALLBACK,
+ passphrase_cb, &data, BUILD_END);
+ }
+ }
+ else
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
+ BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE, secret, BUILD_END);
+ }
+ if (key)
+ {
+ DBG1(DBG_CFG, " loaded %N private key from '%s'",
+ key_type_names, key->get_type(key), path);
+ this->private->insert_last(this->private, key);
+ }
+ else
+ {
+ DBG1(DBG_CFG, " loading private key from '%s' failed", path);
+ }
+ chunk_clear(&secret);
+ }
+ else if (match("PIN", &token))
+ {
+ chunk_t sc = chunk_empty, secret = chunk_empty;
+ char smartcard[32], keyid[22], pin[32];
+ private_key_t *key;
+ u_int slot;
+
+ err_t ugh = extract_value(&sc, &line);
+
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
+ goto error;
+ }
+ if (sc.len == 0)
+ {
+ DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr);
+ goto error;
+ }
+ snprintf(smartcard, sizeof(smartcard), "%.*s", sc.len, sc.ptr);
+ smartcard[sizeof(smartcard) - 1] = '\0';
+
+ /* parse slot and key id. only two formats are supported.
+ * first try %smartcard<slot>:<keyid> */
+ if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2)
+ {
+ snprintf(smartcard, sizeof(smartcard), "%u:%s", slot, keyid);
+ }
+ /* then try %smartcard:<keyid> */
+ else if (sscanf(smartcard, "%%smartcard:%s", keyid) == 1)
+ {
+ snprintf(smartcard, sizeof(smartcard), "%s", keyid);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
+ " supported or invalid", line_nr);
+ goto error;
+ }
+
+ if (!eat_whitespace(&line))
+ {
+ DBG1(DBG_CFG, "line %d: expected PIN", line_nr);
+ goto error;
+ }
+ ugh = extract_secret(&secret, &line);
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh);
+ goto error;
+ }
+ snprintf(pin, sizeof(pin), "%.*s", secret.len, secret.ptr);
+ pin[sizeof(pin) - 1] = '\0';
+
+ /* we assume an RSA key */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_SMARTCARD_KEYID, smartcard,
+ BUILD_SMARTCARD_PIN, pin, BUILD_END);
+
+ if (key)
+ {
+ DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr);
+ this->private->insert_last(this->private, key);
+ }
+ memset(pin, 0, sizeof(pin));
+ chunk_clear(&secret);
+ }
+ else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
+ (match("EAP", &token) && (type = SHARED_EAP)) ||
+ (match("NTLM", &token) && (type = SHARED_NT_HASH)) ||
+ (match("XAUTH", &token) && (type = SHARED_EAP)))
+ {
+ stroke_shared_key_t *shared_key;
+ chunk_t secret = chunk_empty;
+ bool any = TRUE;
+
+ err_t ugh = extract_secret(&secret, &line);
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
+ goto error;
+ }
+ shared_key = stroke_shared_key_create(type, secret);
+ DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
+ ids.len > 0 ? (char*)ids.ptr : "%any");
+ DBG4(DBG_CFG, " secret: %#B", &secret);
+
+ this->shared->insert_last(this->shared, shared_key);
+ while (ids.len > 0)
+ {
+ chunk_t id;
+ identification_t *peer_id;
+
+ ugh = extract_value(&id, &ids);
+ if (ugh != NULL)
+ {
+ DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
+ goto error;
+ }
+ if (id.len == 0)
+ {
+ continue;
+ }
+
+ /* NULL terminate the ID string */
+ *(id.ptr + id.len) = '\0';
+ peer_id = identification_create_from_string(id.ptr);
+ if (peer_id->get_type(peer_id) == ID_ANY)
+ {
+ peer_id->destroy(peer_id);
+ continue;
+ }
+
+ shared_key->add_owner(shared_key, peer_id);
+ any = FALSE;
+ }
+ if (any)
+ {
+ shared_key->add_owner(shared_key,
+ identification_create_from_encoding(ID_ANY, chunk_empty));
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "line %d: token must be either "
+ "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr);
+ goto error;
+ }
+ }
+error:
+ if (level == 0)
+ {
+ this->lock->unlock(this->lock);
+ }
+ chunk_clear(&chunk);
+}
+
+/**
+ * load all certificates from ipsec.d
+ */
+static void load_certs(private_stroke_cred_t *this)
+{
+ DBG1(DBG_CFG, "loading ca certificates from '%s'",
+ CA_CERTIFICATE_DIR);
+ load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
+
+ DBG1(DBG_CFG, "loading aa certificates from '%s'",
+ AA_CERTIFICATE_DIR);
+ load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
+
+ DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
+ OCSP_CERTIFICATE_DIR);
+ load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
+
+ DBG1(DBG_CFG, "loading attribute certificates from '%s'",
+ ATTR_CERTIFICATE_DIR);
+ load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
+
+ DBG1(DBG_CFG, "loading crls from '%s'",
+ CRL_DIR);
+ load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
+}
+
+/**
+ * Implementation of stroke_cred_t.reread.
+ */
+static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt)
+{
+ if (msg->reread.flags & REREAD_SECRETS)
+ {
+ DBG1(DBG_CFG, "rereading secrets");
+ load_secrets(this, SECRETS_FILE, 0, prompt);
+ }
+ if (msg->reread.flags & REREAD_CACERTS)
+ {
+ DBG1(DBG_CFG, "rereading ca certificates from '%s'",
+ CA_CERTIFICATE_DIR);
+ load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
+ }
+ if (msg->reread.flags & REREAD_OCSPCERTS)
+ {
+ DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
+ OCSP_CERTIFICATE_DIR);
+ load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
+ X509_OCSP_SIGNER);
+ }
+ if (msg->reread.flags & REREAD_AACERTS)
+ {
+ DBG1(DBG_CFG, "rereading aa certificates from '%s'",
+ AA_CERTIFICATE_DIR);
+ load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
+ }
+ if (msg->reread.flags & REREAD_ACERTS)
+ {
+ DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
+ ATTR_CERTIFICATE_DIR);
+ load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
+ }
+ if (msg->reread.flags & REREAD_CRLS)
+ {
+ DBG1(DBG_CFG, "rereading crls from '%s'",
+ CRL_DIR);
+ load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
+ }
+}
+
+/**
+ * Implementation of stroke_cred_t.destroy
+ */
+static void destroy(private_stroke_cred_t *this)
+{
+ this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
+ this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
+ this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_cred_t *stroke_cred_create()
+{
+ private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
+
+ this->public.set.create_private_enumerator = (void*)create_private_enumerator;
+ this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
+ this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)cache_cert;
+ this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg, FILE*))reread;
+ this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
+ this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
+ this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
+ this->public.destroy = (void(*)(stroke_cred_t*))destroy;
+
+ this->certs = linked_list_create();
+ this->shared = linked_list_create();
+ this->private = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ load_certs(this);
+ load_secrets(this, SECRETS_FILE, 0, NULL);
+
+ this->cachecrl = FALSE;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h
new file mode 100644
index 000000000..ccee7d87c
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_cred.h
@@ -0,0 +1,84 @@
+/*
+ * 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 stroke_cred stroke_cred
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_CRED_H_
+#define STROKE_CRED_H_
+
+#include <stdio.h>
+
+#include <stroke_msg.h>
+#include <credentials/credential_set.h>
+#include <credentials/certificates/certificate.h>
+
+typedef struct stroke_cred_t stroke_cred_t;
+
+/**
+ * Stroke in-memory credential storage.
+ */
+struct stroke_cred_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Reread secrets from config files.
+ *
+ * @param msg stroke message
+ * @param prompt I/O channel to prompt for private key passhprase
+ */
+ void (*reread)(stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt);
+
+ /**
+ * Load a CA certificate, and serve it through the credential_set.
+ *
+ * @param filename file to load CA cert from
+ * @return reference to loaded certificate, or NULL
+ */
+ certificate_t* (*load_ca)(stroke_cred_t *this, char *filename);
+
+ /**
+ * Load a peer certificate and serve it rhrough the credential_set.
+ *
+ * @param filename file to load peer cert from
+ * @return reference to loaded certificate, or NULL
+ */
+ certificate_t* (*load_peer)(stroke_cred_t *this, char *filename);
+
+ /**
+ * Enable/Disable CRL caching to disk.
+ *
+ * @param enabled TRUE to enable, FALSE to disable
+ */
+ void (*cachecrl)(stroke_cred_t *this, bool enabled);
+
+ /**
+ * Destroy a stroke_cred instance.
+ */
+ void (*destroy)(stroke_cred_t *this);
+};
+
+/**
+ * Create a stroke_cred instance.
+ */
+stroke_cred_t *stroke_cred_create();
+
+#endif /** STROKE_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
new file mode 100644
index 000000000..c2a98da33
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -0,0 +1,1230 @@
+/*
+ * 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.
+ */
+
+#include "stroke_list.h"
+
+#include <time.h>
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/ac.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/pgp_certificate.h>
+#include <credentials/ietf_attributes/ietf_attributes.h>
+#include <config/peer_cfg.h>
+
+/* warning intervals for list functions */
+#define CERT_WARNING_INTERVAL 30 /* days */
+#define CRL_WARNING_INTERVAL 7 /* days */
+#define AC_WARNING_INTERVAL 1 /* day */
+
+typedef struct private_stroke_list_t private_stroke_list_t;
+
+/**
+ * private data of stroke_list
+ */
+struct private_stroke_list_t {
+
+ /**
+ * public functions
+ */
+ stroke_list_t public;
+
+ /**
+ * timestamp of daemon start
+ */
+ time_t uptime;
+
+ /**
+ * strokes attribute provider
+ */
+ stroke_attribute_t *attribute;
+};
+
+/**
+ * log an IKE_SA to out
+ */
+static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
+{
+ ike_sa_id_t *id = ike_sa->get_id(ike_sa);
+ time_t now = time_monotonic(NULL);
+
+ fprintf(out, "%12s[%d]: %N",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
+ ike_sa_state_names, ike_sa->get_state(ike_sa));
+
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
+ {
+ time_t established;
+
+ established = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
+ fprintf(out, " %V ago", &now, &established);
+ }
+
+ fprintf(out, ", %H[%Y]...%H[%Y]\n",
+ ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
+ ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
+
+ if (all)
+ {
+ proposal_t *ike_proposal;
+
+ ike_proposal = ike_sa->get_proposal(ike_sa);
+
+ fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
+ id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
+ id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
+
+
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
+ {
+ time_t rekey, reauth;
+ peer_cfg_t *peer_cfg;
+
+ rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
+ reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ if (rekey)
+ {
+ fprintf(out, ", rekeying in %V", &rekey, &now);
+ }
+ if (reauth)
+ {
+ bool first = TRUE;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+
+ fprintf(out, ", ");
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ if (!first)
+ {
+ fprintf(out, "+");
+ }
+ first = FALSE;
+ fprintf(out, "%N", auth_class_names,
+ auth->get(auth, AUTH_RULE_AUTH_CLASS));
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, " reauthentication in %V", &reauth, &now);
+ }
+ if (!rekey && !reauth)
+ {
+ fprintf(out, ", rekeying disabled");
+ }
+ }
+ fprintf(out, "\n");
+
+ if (ike_proposal)
+ {
+ char buf[BUF_LEN];
+
+ snprintf(buf, BUF_LEN, "%P", ike_proposal);
+ fprintf(out, "%12s[%d]: IKE proposal: %s\n",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
+ buf+4);
+ }
+ }
+}
+
+/**
+ * log an CHILD_SA to out
+ */
+static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
+{
+ time_t use_in, use_out, rekey, now;
+ u_int64_t bytes_in, bytes_out;
+ proposal_t *proposal;
+ child_cfg_t *config = child_sa->get_config(child_sa);
+
+
+ fprintf(out, "%12s{%d}: %N, %N%s",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ child_sa_state_names, child_sa->get_state(child_sa),
+ ipsec_mode_names, child_sa->get_mode(child_sa),
+ config->use_proxy_mode(config) ? "_PROXY" : "");
+
+ if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
+ {
+ fprintf(out, ", %N%s SPIs: %.8x_i %.8x_o",
+ protocol_id_names, child_sa->get_protocol(child_sa),
+ child_sa->has_encap(child_sa) ? " in UDP" : "",
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)));
+
+ if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE)
+ {
+ fprintf(out, ", IPCOMP CPIs: %.4x_i %.4x_o",
+ ntohs(child_sa->get_cpi(child_sa, TRUE)),
+ ntohs(child_sa->get_cpi(child_sa, FALSE)));
+ }
+
+ if (all)
+ {
+ fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa));
+
+ proposal = child_sa->get_proposal(child_sa);
+ if (proposal)
+ {
+ u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
+ u_int16_t encr_size = 0, int_size = 0;
+
+ proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &encr_alg, &encr_size);
+ proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size);
+
+ if (encr_alg != ENCR_UNDEFINED)
+ {
+ fprintf(out, "%N", encryption_algorithm_names, encr_alg);
+ if (encr_size)
+ {
+ fprintf(out, "_%u", encr_size);
+ }
+ }
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ fprintf(out, "/%N", integrity_algorithm_names, int_alg);
+ if (int_size)
+ {
+ fprintf(out, "_%u", int_size);
+ }
+ }
+ }
+
+ now = time_monotonic(NULL);
+ child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
+ fprintf(out, ", %llu bytes_i", bytes_in);
+ if (use_in)
+ {
+ fprintf(out, " (%ds ago)", now - use_in);
+ }
+
+ child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out);
+ fprintf(out, ", %llu bytes_o", bytes_out);
+ if (use_out)
+ {
+ fprintf(out, " (%ds ago)", now - use_out);
+ }
+ fprintf(out, ", rekeying ");
+
+ rekey = child_sa->get_lifetime(child_sa, FALSE);
+ if (rekey)
+ {
+ if (now > rekey)
+ {
+ fprintf(out, "active");
+ }
+ else
+ {
+ fprintf(out, "in %V", &now, &rekey);
+ }
+ }
+ else
+ {
+ fprintf(out, "disabled");
+ }
+
+ }
+ }
+
+ fprintf(out, "\n%12s{%d}: %#R=== %#R\n",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+}
+
+/**
+ * Log a configs local or remote authentication config to out
+ */
+static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
+{
+ enumerator_t *enumerator, *rules;
+ auth_rule_t rule;
+ auth_cfg_t *auth;
+ auth_class_t auth_class;
+ identification_t *id;
+ certificate_t *cert;
+ cert_validation_t valid;
+ char *name;
+
+ name = peer_cfg->get_name(peer_cfg);
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ fprintf(out, "%12s: %s [%Y] uses ", name, local ? "local: " : "remote:",
+ auth->get(auth, AUTH_RULE_IDENTITY));
+
+ auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ if (auth_class != AUTH_CLASS_EAP)
+ {
+ fprintf(out, "%N authentication\n", auth_class_names, auth_class);
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
+ {
+ fprintf(out, "EAP authentication");
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
+ {
+ fprintf(out, "EAP_%d-%d authentication",
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
+ }
+ else
+ {
+ fprintf(out, "%N authentication", eap_type_names,
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
+ }
+ }
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ fprintf(out, " with EAP identity '%Y'", id);
+ }
+ fprintf(out, "\n");
+ }
+
+ cert = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: ca: \"%Y\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_IM_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: im-ca: \"%Y\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: cert: \"%Y\"\n", name,
+ cert->get_subject(cert));
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &id))
+ {
+ if (rule == AUTH_RULE_AC_GROUP)
+ {
+ fprintf(out, "%12s: group: %Y\n", name, id);
+ }
+ }
+ rules->destroy(rules);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of stroke_list_t.status.
+ */
+static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
+{
+ enumerator_t *enumerator, *children;
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
+ bool first, found = FALSE;
+ char *name = msg->status.name;
+
+ if (all)
+ {
+ peer_cfg_t *peer_cfg;
+ char *plugin, *pool;
+ host_t *host;
+ u_int32_t dpd;
+ time_t since, now;
+ u_int size, online, offline;
+
+ now = time_monotonic(NULL);
+ since = time(NULL) - (now - this->uptime);
+
+ fprintf(out, "Status of IKEv2 charon daemon (strongSwan "VERSION"):\n");
+ fprintf(out, " uptime: %V, since %T\n", &now, &this->uptime, &since, FALSE);
+ fprintf(out, " worker threads: %d idle of %d,",
+ charon->processor->get_idle_threads(charon->processor),
+ charon->processor->get_total_threads(charon->processor));
+ fprintf(out, " job queue load: %d,",
+ charon->processor->get_job_load(charon->processor));
+ fprintf(out, " scheduled events: %d\n",
+ charon->scheduler->get_job_load(charon->scheduler));
+ fprintf(out, " loaded plugins: ");
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (enumerator->enumerate(enumerator, &plugin))
+ {
+ fprintf(out, "%s ", plugin);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n");
+
+ first = TRUE;
+ enumerator = this->attribute->create_pool_enumerator(this->attribute);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (name && !streq(name, pool))
+ {
+ continue;
+ }
+ if (first)
+ {
+ first = FALSE;
+ fprintf(out, "Virtual IP pools (size/online/offline):\n");
+ }
+ fprintf(out, " %s: %u/%u/%u\n", pool, size, online, offline);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ fprintf(out, "Listening IP addresses:\n");
+ while (enumerator->enumerate(enumerator, (void**)&host))
+ {
+ fprintf(out, " %H\n", host);
+ }
+ enumerator->destroy(enumerator);
+
+ fprintf(out, "Connections:\n");
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
+ (name && !streq(name, peer_cfg->get_name(peer_cfg))))
+ {
+ continue;
+ }
+
+ ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+ fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
+ ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
+
+ dpd = peer_cfg->get_dpd(peer_cfg);
+ if (dpd)
+ {
+ fprintf(out, ", dpddelay=%us", dpd);
+ }
+ fprintf(out, "\n");
+
+ log_auth_cfgs(out, peer_cfg, TRUE);
+ log_auth_cfgs(out, peer_cfg, FALSE);
+
+ children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (children->enumerate(children, &child_cfg))
+ {
+ linked_list_t *my_ts, *other_ts;
+
+ my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+ other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
+ fprintf(out, "%12s: child: %#R=== %#R", child_cfg->get_name(child_cfg),
+ my_ts, other_ts);
+ my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
+
+ if (dpd)
+ {
+ fprintf(out, ", dpdaction=%N", action_names,
+ child_cfg->get_dpd_action(child_cfg));
+ }
+ fprintf(out, "\n");
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ first = TRUE;
+ enumerator = charon->traps->create_enumerator(charon->traps);
+ while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ {
+ if (first)
+ {
+ fprintf(out, "Routed Connections:\n");
+ first = FALSE;
+ }
+ log_child_sa(out, child_sa, all);
+ }
+ enumerator->destroy(enumerator);
+
+ fprintf(out, "Security Associations:\n");
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ bool ike_printed = FALSE;
+ iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
+
+ if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
+ {
+ log_ike_sa(out, ike_sa, all);
+ found = TRUE;
+ ike_printed = TRUE;
+ }
+
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (name == NULL || streq(name, child_sa->get_name(child_sa)))
+ {
+ if (!ike_printed)
+ {
+ log_ike_sa(out, ike_sa, all);
+ found = TRUE;
+ ike_printed = TRUE;
+ }
+ log_child_sa(out, child_sa, all);
+ }
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ if (name)
+ {
+ fprintf(out, " no match\n");
+ }
+ else
+ {
+ fprintf(out, " none\n");
+ }
+ }
+}
+
+/**
+ * create a unique certificate list without duplicates
+ * certicates having the same issuer are grouped together.
+ */
+static linked_list_t* create_unique_cert_list(certificate_type_t type)
+{
+ linked_list_t *list = linked_list_create();
+ enumerator_t *enumerator = charon->credentials->create_cert_enumerator(
+ charon->credentials, type, KEY_ANY,
+ NULL, FALSE);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ iterator_t *iterator = list->create_iterator(list, TRUE);
+ identification_t *issuer = cert->get_issuer(cert);
+ bool previous_same, same = FALSE, last = TRUE;
+ certificate_t *list_cert;
+
+ while (iterator->iterate(iterator, (void**)&list_cert))
+ {
+ /* exit if we have a duplicate? */
+ if (list_cert->equals(list_cert, cert))
+ {
+ last = FALSE;
+ break;
+ }
+ /* group certificates with same issuer */
+ previous_same = same;
+ same = list_cert->has_issuer(list_cert, issuer);
+ if (previous_same && !same)
+ {
+ iterator->insert_before(iterator, (void *)cert->get_ref(cert));
+ last = FALSE;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (last)
+ {
+ list->insert_last(list, (void *)cert->get_ref(cert));
+ }
+ }
+ enumerator->destroy(enumerator);
+ return list;
+}
+
+/**
+ * Print a single public key.
+ */
+static void list_public_key(public_key_t *public, FILE *out)
+{
+ private_key_t *private = NULL;
+ chunk_t keyid;
+ identification_t *id;
+ auth_cfg_t *auth;
+
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+ {
+ id = identification_create_from_encoding(ID_KEY_ID, keyid);
+ auth = auth_cfg_create();
+ private = charon->credentials->get_private(charon->credentials,
+ public->get_type(public), id, auth);
+ auth->destroy(auth);
+ id->destroy(id);
+ }
+
+ fprintf(out, " pubkey: %N %d bits%s\n",
+ key_type_names, public->get_type(public),
+ public->get_keysize(public) * 8,
+ private ? ", has private key" : "");
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ {
+ fprintf(out, " keyid: %#B\n", &keyid);
+ }
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+ {
+ fprintf(out, " subjkey: %#B\n", &keyid);
+ }
+ DESTROY_IF(private);
+}
+
+/**
+ * list all raw public keys
+ */
+static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
+{
+ bool first = TRUE;
+
+ enumerator_t *enumerator = list->create_enumerator(list);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ public_key_t *public = cert->get_public_key(cert);
+
+ if (public)
+ {
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of Raw Public Keys:\n");
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+
+ list_public_key(public, out);
+ public->destroy(public);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * list OpenPGP certificates
+ */
+static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out)
+{
+ bool first = TRUE;
+ time_t now = time(NULL);
+ enumerator_t *enumerator = list->create_enumerator(list);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ time_t created, until;
+ public_key_t *public;
+ pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
+ chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
+
+ if (first)
+ {
+
+ fprintf(out, "\n");
+ fprintf(out, "List of PGP End Entity Certificates:\n");
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+ fprintf(out, " userid: '%Y'\n", cert->get_subject(cert));
+
+ fprintf(out, " digest: %#B\n", &fingerprint);
+
+ /* list validity */
+ cert->get_validity(cert, &now, &created, &until);
+ fprintf(out, " created: %T\n", &created, utc);
+ fprintf(out, " until: %T%s\n", &until, utc,
+ (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ list_public_key(public, out);
+ public->destroy(public);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * list all X.509 certificates matching the flags
+ */
+static void stroke_list_certs(linked_list_t *list, char *label,
+ x509_flag_t flags, bool utc, FILE *out)
+{
+ bool first = TRUE;
+ time_t now = time(NULL);
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ x509_flag_t flag_mask;
+
+ /* mask all auxiliary flags */
+ flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH |
+ X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS );
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ x509_t *x509 = (x509_t*)cert;
+ x509_flag_t x509_flags = x509->get_flags(x509) & flag_mask;
+
+ /* list only if flag is set or flag == 0 */
+ if ((x509_flags & flags) || (x509_flags == flags))
+ {
+ enumerator_t *enumerator;
+ identification_t *altName;
+ bool first_altName = TRUE;
+ int pathlen;
+ chunk_t serial, authkey;
+ time_t notBefore, notAfter;
+ public_key_t *public;
+
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of %s:\n", label);
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+
+ /* list subjectAltNames */
+ enumerator = x509->create_subjectAltName_enumerator(x509);
+ while (enumerator->enumerate(enumerator, (void**)&altName))
+ {
+ if (first_altName)
+ {
+ fprintf(out, " altNames: ");
+ first_altName = FALSE;
+ }
+ else
+ {
+ fprintf(out, ", ");
+ }
+ fprintf(out, "%Y", altName);
+ }
+ if (!first_altName)
+ {
+ fprintf(out, "\n");
+ }
+ enumerator->destroy(enumerator);
+
+ fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert));
+ fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
+ serial = x509->get_serial(x509);
+ fprintf(out, " serial: %#B\n", &serial);
+
+ /* list validity */
+ cert->get_validity(cert, &now, &notBefore, &notAfter);
+ fprintf(out, " validity: not before %T, ", &notBefore, utc);
+ if (now < notBefore)
+ {
+ fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
+ }
+ else
+ {
+ fprintf(out, "ok\n");
+ }
+ fprintf(out, " not after %T, ", &notAfter, utc);
+ if (now > notAfter)
+ {
+ fprintf(out, "expired (%V ago)\n", &now, &notAfter);
+ }
+ else
+ {
+ fprintf(out, "ok");
+ if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
+ {
+ fprintf(out, " (expires in %V)", &now, &notAfter);
+ }
+ fprintf(out, " \n");
+ }
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ list_public_key(public, out);
+ public->destroy(public);
+ }
+
+ /* list optional authorityKeyIdentifier */
+ authkey = x509->get_authKeyIdentifier(x509);
+ if (authkey.ptr)
+ {
+ fprintf(out, " authkey: %#B\n", &authkey);
+ }
+
+ /* list optional pathLenConstraint */
+ pathlen = x509->get_pathLenConstraint(x509);
+ if (pathlen != X509_NO_PATH_LEN_CONSTRAINT)
+ {
+ fprintf(out, " pathlen: %d\n", pathlen);
+ }
+
+ /* list optional ipAddrBlocks */
+ if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+ {
+ traffic_selector_t *ipAddrBlock;
+ bool first_ipAddrBlock = TRUE;
+
+ fprintf(out, " addresses: ");
+ enumerator = x509->create_ipAddrBlock_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &ipAddrBlock))
+ {
+ if (first_ipAddrBlock)
+ {
+ first_ipAddrBlock = FALSE;
+ }
+ else
+ {
+ fprintf(out, ", ");
+ }
+ fprintf(out, "%R", ipAddrBlock);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n");
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * list all X.509 attribute certificates
+ */
+static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
+{
+ bool first = TRUE;
+ time_t thisUpdate, nextUpdate, now = time(NULL);
+ enumerator_t *enumerator = list->create_enumerator(list);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ ac_t *ac = (ac_t*)cert;
+ identification_t *id;
+ ietf_attributes_t *groups;
+ chunk_t chunk;
+
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of X.509 Attribute Certificates:\n");
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+
+ id = cert->get_subject(cert);
+ if (id)
+ {
+ fprintf(out, " holder: \"%Y\"\n", id);
+ }
+ id = ac->get_holderIssuer(ac);
+ if (id)
+ {
+ fprintf(out, " hissuer: \"%Y\"\n", id);
+ }
+ chunk = ac->get_holderSerial(ac);
+ if (chunk.ptr)
+ {
+ fprintf(out, " hserial: %#B\n", &chunk);
+ }
+ groups = ac->get_groups(ac);
+ if (groups)
+ {
+ fprintf(out, " groups: %s\n", groups->get_string(groups));
+ groups->destroy(groups);
+ }
+ fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
+ chunk = ac->get_serial(ac);
+ fprintf(out, " serial: %#B\n", &chunk);
+
+ /* list validity */
+ cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
+ fprintf(out, " updates: this %T\n", &thisUpdate, utc);
+ fprintf(out, " next %T, ", &nextUpdate, utc);
+ if (now > nextUpdate)
+ {
+ fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
+ }
+ else
+ {
+ fprintf(out, "ok");
+ if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24)
+ {
+ fprintf(out, " (expires in %V)", &now, &nextUpdate);
+ }
+ fprintf(out, " \n");
+ }
+
+ /* list optional authorityKeyIdentifier */
+ chunk = ac->get_authKeyIdentifier(ac);
+ if (chunk.ptr)
+ {
+ fprintf(out, " authkey: %#B\n", &chunk);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * list all X.509 CRLs
+ */
+static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
+{
+ bool first = TRUE;
+ time_t thisUpdate, nextUpdate, now = time(NULL);
+ enumerator_t *enumerator = list->create_enumerator(list);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ crl_t *crl = (crl_t*)cert;
+ chunk_t chunk;
+
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of X.509 CRLs:\n");
+ first = FALSE;
+ }
+ fprintf(out, "\n");
+
+ fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
+
+ /* list optional crlNumber */
+ chunk = crl->get_serial(crl);
+ if (chunk.ptr)
+ {
+ fprintf(out, " serial: %#B\n", &chunk);
+ }
+
+ /* count the number of revoked certificates */
+ {
+ int count = 0;
+ enumerator_t *enumerator = crl->create_enumerator(crl);
+
+ while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
+ {
+ count++;
+ }
+ fprintf(out, " revoked: %d certificate%s\n", count,
+ (count == 1)? "" : "s");
+ enumerator->destroy(enumerator);
+ }
+
+ /* list validity */
+ cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
+ fprintf(out, " updates: this %T\n", &thisUpdate, utc);
+ fprintf(out, " next %T, ", &nextUpdate, utc);
+ if (now > nextUpdate)
+ {
+ fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
+ }
+ else
+ {
+ fprintf(out, "ok");
+ if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
+ {
+ fprintf(out, " (expires in %V)", &now, &nextUpdate);
+ }
+ fprintf(out, " \n");
+ }
+
+ /* list optional authorityKeyIdentifier */
+ chunk = crl->get_authKeyIdentifier(crl);
+ if (chunk.ptr)
+ {
+ fprintf(out, " authkey: %#B\n", &chunk);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * list all OCSP responses
+ */
+static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
+{
+ bool first = TRUE;
+ enumerator_t *enumerator = list->create_enumerator(list);
+ certificate_t *cert;
+
+ while (enumerator->enumerate(enumerator, (void**)&cert))
+ {
+ if (first)
+ {
+ fprintf(out, "\n");
+ fprintf(out, "List of OCSP responses:\n");
+ fprintf(out, "\n");
+ first = FALSE;
+ }
+
+ fprintf(out, " signer: \"%Y\"\n", cert->get_issuer(cert));
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * List of registered cryptographical algorithms
+ */
+static void list_algs(FILE *out)
+{
+ enumerator_t *enumerator;
+ encryption_algorithm_t encryption;
+ integrity_algorithm_t integrity;
+ hash_algorithm_t hash;
+ pseudo_random_function_t prf;
+ diffie_hellman_group_t group;
+
+ fprintf(out, "\n");
+ fprintf(out, "List of registered IKEv2 Algorithms:\n");
+ fprintf(out, "\n encryption: ");
+ enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &encryption))
+ {
+ fprintf(out, "%N ", encryption_algorithm_names, encryption);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n integrity: ");
+ enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &integrity))
+ {
+ fprintf(out, "%N ", integrity_algorithm_names, integrity);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n hasher: ");
+ enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &hash))
+ {
+ fprintf(out, "%N ", hash_algorithm_names, hash);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n prf: ");
+ enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &prf))
+ {
+ fprintf(out, "%N ", pseudo_random_function_names, prf);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n dh-group: ");
+ enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &group))
+ {
+ fprintf(out, "%N ", diffie_hellman_group_names, group);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n");
+}
+
+/**
+ * Implementation of stroke_list_t.list.
+ */
+static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+{
+ linked_list_t *cert_list = NULL;
+
+ if (msg->list.flags & LIST_PUBKEYS)
+ {
+ linked_list_t *pubkey_list = create_unique_cert_list(CERT_TRUSTED_PUBKEY);
+
+ stroke_list_pubkeys(pubkey_list, msg->list.utc, out);
+ pubkey_list->destroy_offset(pubkey_list, offsetof(certificate_t, destroy));
+ }
+ if (msg->list.flags & LIST_CERTS)
+ {
+ linked_list_t *pgp_list = create_unique_cert_list(CERT_GPG);
+
+ stroke_list_pgp(pgp_list, msg->list.utc, out);
+ pgp_list->destroy_offset(pgp_list, offsetof(certificate_t, destroy));
+ }
+ if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
+ {
+ cert_list = create_unique_cert_list(CERT_X509);
+ }
+ if (msg->list.flags & LIST_CERTS)
+ {
+ stroke_list_certs(cert_list, "X.509 End Entity Certificates",
+ X509_NONE, msg->list.utc, out);
+ }
+ if (msg->list.flags & LIST_CACERTS)
+ {
+ stroke_list_certs(cert_list, "X.509 CA Certificates",
+ X509_CA, msg->list.utc, out);
+ }
+ if (msg->list.flags & LIST_OCSPCERTS)
+ {
+ stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates",
+ X509_OCSP_SIGNER, msg->list.utc, out);
+ }
+ if (msg->list.flags & LIST_AACERTS)
+ {
+ stroke_list_certs(cert_list, "X.509 AA Certificates",
+ X509_AA, msg->list.utc, out);
+ }
+ DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
+
+ if (msg->list.flags & LIST_ACERTS)
+ {
+ linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC);
+
+ stroke_list_acerts(ac_list, msg->list.utc, out);
+ ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy));
+ }
+ if (msg->list.flags & LIST_CRLS)
+ {
+ linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL);
+
+ stroke_list_crls(crl_list, msg->list.utc, out);
+ crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy));
+ }
+ if (msg->list.flags & LIST_OCSP)
+ {
+ linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE);
+
+ stroke_list_ocsp(ocsp_list, msg->list.utc, out);
+
+ ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy));
+ }
+ if (msg->list.flags & LIST_ALGS)
+ {
+ list_algs(out);
+ }
+}
+
+/**
+ * Print leases of a single pool
+ */
+static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
+ host_t *address, u_int size, u_int online, u_int offline)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+ host_t *lease;
+ bool on;
+ int found = 0;
+
+ fprintf(out, "Leases in pool '%s', usage: %lu/%lu, %lu online\n",
+ pool, online + offline, size, online);
+ enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
+ while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
+ {
+ if (!address || address->ip_equals(address, lease))
+ {
+ fprintf(out, " %15H %s '%Y'\n",
+ lease, on ? "online" : "offline", id);
+ found++;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ fprintf(out, " no matching leases found\n");
+ }
+}
+
+/**
+ * Implementation of stroke_list_t.leases
+ */
+static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+{
+ enumerator_t *enumerator;
+ u_int size, offline, online;
+ host_t *address = NULL;
+ char *pool;
+ int found = 0;
+
+ if (msg->leases.address)
+ {
+ address = host_create_from_string(msg->leases.address, 0);
+ }
+
+ enumerator = this->attribute->create_pool_enumerator(this->attribute);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (!msg->leases.pool || streq(msg->leases.pool, pool))
+ {
+ pool_leases(this, out, pool, address, size, online, offline);
+ found++;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ if (msg->leases.pool)
+ {
+ fprintf(out, "pool '%s' not found\n", msg->leases.pool);
+ }
+ else
+ {
+ fprintf(out, "no pools found\n");
+ }
+ }
+ DESTROY_IF(address);
+}
+
+/**
+ * Implementation of stroke_list_t.destroy
+ */
+static void destroy(private_stroke_list_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
+{
+ private_stroke_list_t *this = malloc_thing(private_stroke_list_t);
+
+ this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list;
+ this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status;
+ this->public.leases = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))leases;
+ this->public.destroy = (void(*)(stroke_list_t*))destroy;
+
+ this->uptime = time_monotonic(NULL);
+ this->attribute = attribute;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_list.h b/src/libcharon/plugins/stroke/stroke_list.h
new file mode 100644
index 000000000..b5bedc6c2
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_list.h
@@ -0,0 +1,74 @@
+/*
+ * 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 stroke_list stroke_list
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_LIST_H_
+#define STROKE_LIST_H_
+
+#include "stroke_attribute.h"
+
+#include <stroke_msg.h>
+#include <library.h>
+
+typedef struct stroke_list_t stroke_list_t;
+
+/**
+ * Log status information to stroke console
+ */
+struct stroke_list_t {
+
+ /**
+ * List certificate information to stroke console.
+ *
+ * @param msg stroke message
+ * @param out stroke console stream
+ */
+ void (*list)(stroke_list_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Log status information to stroke console.
+ *
+ * @param msg stroke message
+ * @param out stroke console stream
+ * @param all TRUE for "statusall"
+ */
+ void (*status)(stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all);
+
+ /**
+ * Log pool leases to stroke console.
+ *
+ * @param msg stroke message
+ * @param out stroke console stream
+ */
+ void (*leases)(stroke_list_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Destroy a stroke_list instance.
+ */
+ void (*destroy)(stroke_list_t *this);
+};
+
+/**
+ * Create a stroke_list instance.
+ *
+ * @param attribute strokes attribute provider
+ */
+stroke_list_t *stroke_list_create(stroke_attribute_t *attribute);
+
+#endif /** STROKE_LIST_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c
new file mode 100644
index 000000000..4361e5050
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_plugin.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "stroke_plugin.h"
+
+#include <library.h>
+#include "stroke_socket.h"
+
+typedef struct private_stroke_plugin_t private_stroke_plugin_t;
+
+/**
+ * private data of stroke_plugin
+ */
+struct private_stroke_plugin_t {
+
+ /**
+ * public functions
+ */
+ stroke_plugin_t public;
+
+ /**
+ * stroke socket, receives strokes
+ */
+ stroke_socket_t *socket;
+};
+
+/**
+ * Implementation of stroke_plugin_t.destroy
+ */
+static void destroy(private_stroke_plugin_t *this)
+{
+ this->socket->destroy(this->socket);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *stroke_plugin_create()
+{
+ private_stroke_plugin_t *this = malloc_thing(private_stroke_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->socket = stroke_socket_create();
+ if (this->socket == NULL)
+ {
+ free(this);
+ return NULL;
+ }
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_plugin.h b/src/libcharon/plugins/stroke/stroke_plugin.h
new file mode 100644
index 000000000..464979910
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_plugin.h
@@ -0,0 +1,45 @@
+/*
+ * 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 stroke stroke
+ * @ingroup cplugins
+ *
+ * @defgroup stroke_plugin stroke_plugin
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_PLUGIN_H_
+#define STROKE_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct stroke_plugin_t stroke_plugin_t;
+
+/**
+ * strongSwan 2.x style configuration and control interface.
+ *
+ * Stroke is a home-brewed communication interface inspired by whack. It
+ * uses a unix socket (/var/run/charon.ctl).
+ */
+struct stroke_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** STROKE_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.c b/src/libcharon/plugins/stroke/stroke_shared_key.c
new file mode 100644
index 000000000..4f716e83a
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_shared_key.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "stroke_shared_key.h"
+
+#include <utils/linked_list.h>
+
+typedef struct private_stroke_shared_key_t private_stroke_shared_key_t;
+
+/**
+ * private data of shared_key
+ */
+struct private_stroke_shared_key_t {
+
+ /**
+ * implements shared_key_t
+ */
+ stroke_shared_key_t public;
+
+ /**
+ * type of this key
+ */
+ shared_key_type_t type;
+
+ /**
+ * data of the key
+ */
+ chunk_t key;
+
+ /**
+ * list of key owners, as identification_t
+ */
+ linked_list_t *owners;
+
+ /**
+ * reference counter
+ */
+ refcount_t ref;
+};
+
+/**
+ * Implementation of shared_key_t.get_type.
+ */
+static shared_key_type_t get_type(private_stroke_shared_key_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of shared_key_t.get_ref.
+ */
+static private_stroke_shared_key_t* get_ref(private_stroke_shared_key_t *this)
+{
+ ref_get(&this->ref);
+ return this;
+}
+
+/**
+ * Implementation of shared_key_t.get_key.
+ */
+static chunk_t get_key(private_stroke_shared_key_t *this)
+{
+ return this->key;
+}
+
+/**
+ * Implementation of stroke_shared_key_t.has_owner.
+ */
+static id_match_t has_owner(private_stroke_shared_key_t *this, identification_t *owner)
+{
+ enumerator_t *enumerator;
+ id_match_t match, best = ID_MATCH_NONE;
+ identification_t *current;
+
+ enumerator = this->owners->create_enumerator(this->owners);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ match = owner->matches(owner, current);
+ if (match > best)
+ {
+ best = match;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return best;
+}
+/**
+ * Implementation of stroke_shared_key_t.add_owner.
+ */
+static void add_owner(private_stroke_shared_key_t *this, identification_t *owner)
+{
+ this->owners->insert_last(this->owners, owner);
+}
+
+/**
+ * Implementation of stroke_shared_key_t.destroy
+ */
+static void destroy(private_stroke_shared_key_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->owners->destroy_offset(this->owners, offsetof(identification_t, destroy));
+ chunk_free(&this->key);
+ free(this);
+ }
+}
+
+/**
+ * create a shared key
+ */
+stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key)
+{
+ private_stroke_shared_key_t *this = malloc_thing(private_stroke_shared_key_t);
+
+ this->public.shared.get_type = (shared_key_type_t(*)(shared_key_t*))get_type;
+ this->public.shared.get_key = (chunk_t(*)(shared_key_t*))get_key;
+ this->public.shared.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref;
+ this->public.shared.destroy = (void(*)(shared_key_t*))destroy;
+ this->public.add_owner = (void(*)(stroke_shared_key_t*, identification_t *owner))add_owner;
+ this->public.has_owner = (id_match_t(*)(stroke_shared_key_t*, identification_t *owner))has_owner;
+
+ this->owners = linked_list_create();
+ this->type = type;
+ this->key = key;
+ this->ref = 1;
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.h b/src/libcharon/plugins/stroke/stroke_shared_key.h
new file mode 100644
index 000000000..05ad55083
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_shared_key.h
@@ -0,0 +1,60 @@
+/*
+ * 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 stroke_shared_key stroke_shared_key
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_SHARED_KEY_H_
+#define STROKE_SHARED_KEY_H_
+
+#include <utils/identification.h>
+#include <credentials/keys/shared_key.h>
+
+typedef struct stroke_shared_key_t stroke_shared_key_t;
+
+/**
+ * Shared key implementation for keys read from ipsec.secrets
+ */
+struct stroke_shared_key_t {
+
+ /**
+ * Implements the shared_key_t interface.
+ */
+ shared_key_t shared;
+
+ /**
+ * Add an owner to the key.
+ *
+ * @param owner owner to add
+ */
+ void (*add_owner)(stroke_shared_key_t *this, identification_t *owner);
+
+ /**
+ * Check if a key has a specific owner.
+ *
+ * @param owner owner to check
+ * @return best match found
+ */
+ id_match_t (*has_owner)(stroke_shared_key_t *this, identification_t *owner);
+};
+
+/**
+ * Create a stroke_shared_key instance.
+ */
+stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key);
+
+#endif /** STROKE_SHARED_KEY_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
new file mode 100644
index 000000000..56c18da38
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -0,0 +1,671 @@
+/*
+ * 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.
+ */
+
+#include "stroke_socket.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <processing/jobs/callback_job.h>
+#include <hydra.h>
+#include <daemon.h>
+#include <threading/thread.h>
+
+#include "stroke_config.h"
+#include "stroke_control.h"
+#include "stroke_cred.h"
+#include "stroke_ca.h"
+#include "stroke_attribute.h"
+#include "stroke_list.h"
+
+typedef struct stroke_job_context_t stroke_job_context_t;
+typedef struct private_stroke_socket_t private_stroke_socket_t;
+
+/**
+ * private data of stroke_socket
+ */
+struct private_stroke_socket_t {
+
+ /**
+ * public functions
+ */
+ stroke_socket_t public;
+
+ /**
+ * Unix socket to listen for strokes
+ */
+ int socket;
+
+ /**
+ * job accepting stroke messages
+ */
+ callback_job_t *job;
+
+ /**
+ * configuration backend
+ */
+ stroke_config_t *config;
+
+ /**
+ * attribute provider
+ */
+ stroke_attribute_t *attribute;
+
+ /**
+ * controller to control daemon
+ */
+ stroke_control_t *control;
+
+ /**
+ * credential set
+ */
+ stroke_cred_t *cred;
+
+ /**
+ * CA sections
+ */
+ stroke_ca_t *ca;
+
+ /**
+ * Status information logging
+ */
+ stroke_list_t *list;
+};
+
+/**
+ * job context to pass to processing thread
+ */
+struct stroke_job_context_t {
+
+ /**
+ * file descriptor to read from
+ */
+ int fd;
+
+ /**
+ * global stroke interface
+ */
+ private_stroke_socket_t *this;
+};
+
+/**
+ * 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
+ * stroke_msg). They must be corrected if they reach our address
+ * space...
+ */
+static void pop_string(stroke_msg_t *msg, char **string)
+{
+ if (*string == NULL)
+ {
+ return;
+ }
+
+ /* check for sanity of string pointer and string */
+ if (string < (char**)msg ||
+ string > (char**)msg + sizeof(stroke_msg_t) ||
+ (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
+ (unsigned long)*string > msg->length)
+ {
+ *string = "(invalid pointer in stroke msg)";
+ }
+ else
+ {
+ *string = (char*)msg + (unsigned long)*string;
+ }
+}
+
+/**
+ * Pop the strings of a stroke_end_t struct and log them for debugging purposes
+ */
+static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
+{
+ pop_string(msg, &end->address);
+ pop_string(msg, &end->subnets);
+ pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->auth);
+ pop_string(msg, &end->auth2);
+ pop_string(msg, &end->id);
+ pop_string(msg, &end->id2);
+ pop_string(msg, &end->cert);
+ pop_string(msg, &end->cert2);
+ pop_string(msg, &end->ca);
+ pop_string(msg, &end->ca2);
+ pop_string(msg, &end->groups);
+ 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, " %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, " %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, " %supdown=%s", label, end->updown);
+}
+
+/**
+ * Add a connection to the configuration list
+ */
+static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
+{
+ pop_string(msg, &msg->add_conn.name);
+ DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
+
+ DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
+ pop_end(msg, "left", &msg->add_conn.me);
+ pop_end(msg, "right", &msg->add_conn.other);
+ pop_string(msg, &msg->add_conn.eap_identity);
+ pop_string(msg, &msg->add_conn.algorithms.ike);
+ pop_string(msg, &msg->add_conn.algorithms.esp);
+ 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, " ike=%s", msg->add_conn.algorithms.ike);
+ DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
+ 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);
+
+ this->config->add(this->config, msg);
+ this->attribute->add_pool(this->attribute, msg);
+}
+
+/**
+ * Delete a connection from the list
+ */
+static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
+{
+ pop_string(msg, &msg->del_conn.name);
+ DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
+
+ this->config->del(this->config, msg);
+ this->attribute->del_pool(this->attribute, msg);
+}
+
+/**
+ * initiate a connection by name
+ */
+static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->initiate.name);
+ DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
+
+ this->control->initiate(this->control, msg, out);
+}
+
+/**
+ * terminate a connection by name
+ */
+static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->terminate.name);
+ DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
+
+ this->control->terminate(this->control, msg, out);
+}
+
+/**
+ * terminate a connection by peers virtual IP
+ */
+static void stroke_terminate_srcip(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->terminate_srcip.start);
+ pop_string(msg, &msg->terminate_srcip.end);
+ DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
+ msg->terminate_srcip.start, msg->terminate_srcip.end);
+
+ this->control->terminate_srcip(this->control, msg, out);
+}
+
+/**
+ * route a policy (install SPD entries)
+ */
+static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->route.name);
+ DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
+
+ this->control->route(this->control, msg, out);
+}
+
+/**
+ * unroute a policy
+ */
+static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->terminate.name);
+ DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
+
+ this->control->unroute(this->control, msg, out);
+}
+
+/**
+ * Add a ca information record to the cainfo list
+ */
+static void stroke_add_ca(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->add_ca.name);
+ DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
+
+ pop_string(msg, &msg->add_ca.cacert);
+ pop_string(msg, &msg->add_ca.crluri);
+ pop_string(msg, &msg->add_ca.crluri2);
+ 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);
+
+ this->ca->add(this->ca, msg);
+}
+
+/**
+ * Delete a ca information record from the cainfo list
+ */
+static void stroke_del_ca(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->del_ca.name);
+ DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
+
+ this->ca->del(this->ca, msg);
+}
+
+
+/**
+ * show status of daemon
+ */
+static void stroke_status(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out, bool all)
+{
+ pop_string(msg, &(msg->status.name));
+
+ this->list->status(this->list, msg, out, all);
+}
+
+/**
+ * list various information
+ */
+static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ if (msg->list.flags & LIST_CAINFOS)
+ {
+ this->ca->list(this->ca, msg, out);
+ }
+ this->list->list(this->list, msg, out);
+}
+
+/**
+ * reread various information
+ */
+static void stroke_reread(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ this->cred->reread(this->cred, msg, out);
+}
+
+/**
+ * purge various information
+ */
+static void stroke_purge(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ if (msg->purge.flags & PURGE_OCSP)
+ {
+ charon->credentials->flush_cache(charon->credentials,
+ CERT_X509_OCSP_RESPONSE);
+ }
+ if (msg->purge.flags & PURGE_IKE)
+ {
+ this->control->purge_ike(this->control, msg, out);
+ }
+}
+
+/**
+ * list pool leases
+ */
+static void stroke_leases(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->leases.pool);
+ pop_string(msg, &msg->leases.address);
+
+ this->list->leases(this->list, msg, out);
+}
+
+debug_t get_group_from_name(char *type)
+{
+ if (strcaseeq(type, "any")) return DBG_ANY;
+ else if (strcaseeq(type, "mgr")) return DBG_MGR;
+ else if (strcaseeq(type, "ike")) return DBG_IKE;
+ else if (strcaseeq(type, "chd")) return DBG_CHD;
+ else if (strcaseeq(type, "job")) return DBG_JOB;
+ else if (strcaseeq(type, "cfg")) return DBG_CFG;
+ else if (strcaseeq(type, "knl")) return DBG_KNL;
+ else if (strcaseeq(type, "net")) return DBG_NET;
+ else if (strcaseeq(type, "enc")) return DBG_ENC;
+ else if (strcaseeq(type, "lib")) return DBG_LIB;
+ else return -1;
+}
+
+/**
+ * set the verbosity debug output
+ */
+static void stroke_loglevel(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ enumerator_t *enumerator;
+ sys_logger_t *sys_logger;
+ file_logger_t *file_logger;
+ debug_t group;
+
+ pop_string(msg, &(msg->loglevel.type));
+ DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
+ msg->loglevel.level, msg->loglevel.type);
+
+ group = get_group_from_name(msg->loglevel.type);
+ if (group < 0)
+ {
+ fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
+ return;
+ }
+ /* we set the loglevel on ALL sys- and file-loggers */
+ enumerator = charon->sys_loggers->create_enumerator(charon->sys_loggers);
+ while (enumerator->enumerate(enumerator, &sys_logger))
+ {
+ sys_logger->set_level(sys_logger, group, msg->loglevel.level);
+ }
+ enumerator->destroy(enumerator);
+ enumerator = charon->file_loggers->create_enumerator(charon->file_loggers);
+ while (enumerator->enumerate(enumerator, &file_logger))
+ {
+ file_logger->set_level(file_logger, group, msg->loglevel.level);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * set various config options
+ */
+static void stroke_config(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ this->cred->cachecrl(this->cred, msg->config.cachecrl);
+}
+
+/**
+ * destroy a job context
+ */
+static void stroke_job_context_destroy(stroke_job_context_t *this)
+{
+ if (this->fd)
+ {
+ close(this->fd);
+ }
+ free(this);
+}
+
+/**
+ * process a stroke request from the socket pointed by "fd"
+ */
+static job_requeue_t process(stroke_job_context_t *ctx)
+{
+ stroke_msg_t *msg;
+ u_int16_t msg_length;
+ ssize_t bytes_read;
+ FILE *out;
+ private_stroke_socket_t *this = ctx->this;
+ int strokefd = ctx->fd;
+
+ /* peek the length */
+ bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
+ if (bytes_read != sizeof(msg_length))
+ {
+ DBG1(DBG_CFG, "reading length of stroke message failed: %s",
+ strerror(errno));
+ return JOB_REQUEUE_NONE;
+ }
+
+ /* read message */
+ msg = alloca(msg_length);
+ bytes_read = recv(strokefd, msg, msg_length, 0);
+ if (bytes_read != msg_length)
+ {
+ DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
+ return JOB_REQUEUE_NONE;
+ }
+
+ out = fdopen(strokefd, "w+");
+ if (out == NULL)
+ {
+ DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
+ return JOB_REQUEUE_NONE;
+ }
+
+ DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
+
+ switch (msg->type)
+ {
+ case STR_INITIATE:
+ stroke_initiate(this, msg, out);
+ break;
+ case STR_ROUTE:
+ stroke_route(this, msg, out);
+ break;
+ case STR_UNROUTE:
+ stroke_unroute(this, msg, out);
+ break;
+ case STR_TERMINATE:
+ stroke_terminate(this, msg, out);
+ break;
+ case STR_TERMINATE_SRCIP:
+ stroke_terminate_srcip(this, msg, out);
+ break;
+ case STR_STATUS:
+ stroke_status(this, msg, out, FALSE);
+ break;
+ case STR_STATUS_ALL:
+ stroke_status(this, msg, out, TRUE);
+ break;
+ case STR_ADD_CONN:
+ stroke_add_conn(this, msg);
+ break;
+ case STR_DEL_CONN:
+ stroke_del_conn(this, msg);
+ break;
+ case STR_ADD_CA:
+ stroke_add_ca(this, msg, out);
+ break;
+ case STR_DEL_CA:
+ stroke_del_ca(this, msg, out);
+ break;
+ case STR_LOGLEVEL:
+ stroke_loglevel(this, msg, out);
+ break;
+ case STR_CONFIG:
+ stroke_config(this, msg, out);
+ break;
+ case STR_LIST:
+ stroke_list(this, msg, out);
+ break;
+ case STR_REREAD:
+ stroke_reread(this, msg, out);
+ break;
+ case STR_PURGE:
+ stroke_purge(this, msg, out);
+ break;
+ case STR_LEASES:
+ stroke_leases(this, msg, out);
+ break;
+ default:
+ DBG1(DBG_CFG, "received unknown stroke");
+ break;
+ }
+ fclose(out);
+ /* fclose() closes underlying FD */
+ ctx->fd = 0;
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of private_stroke_socket_t.stroke_receive.
+ */
+static job_requeue_t receive(private_stroke_socket_t *this)
+{
+ struct sockaddr_un strokeaddr;
+ int strokeaddrlen = sizeof(strokeaddr);
+ int strokefd;
+ bool oldstate;
+ callback_job_t *job;
+ stroke_job_context_t *ctx;
+
+ oldstate = thread_cancelability(TRUE);
+ strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
+ thread_cancelability(oldstate);
+
+ if (strokefd < 0)
+ {
+ DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
+ return JOB_REQUEUE_FAIR;
+ }
+
+ ctx = malloc_thing(stroke_job_context_t);
+ ctx->fd = strokefd;
+ ctx->this = this;
+ job = callback_job_create((callback_job_cb_t)process,
+ ctx, (void*)stroke_job_context_destroy, this->job);
+ charon->processor->queue_job(charon->processor, (job_t*)job);
+
+ return JOB_REQUEUE_FAIR;
+}
+
+
+/**
+ * initialize and open stroke socket
+ */
+static bool open_socket(private_stroke_socket_t *this)
+{
+ struct sockaddr_un socket_addr;
+ mode_t old;
+
+ socket_addr.sun_family = AF_UNIX;
+ strcpy(socket_addr.sun_path, STROKE_SOCKET);
+
+ /* set up unix socket */
+ this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (this->socket == -1)
+ {
+ DBG1(DBG_CFG, "could not create stroke socket");
+ return FALSE;
+ }
+
+ unlink(socket_addr.sun_path);
+ old = umask(~(S_IRWXU | S_IRWXG));
+ if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
+ {
+ DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno));
+ close(this->socket);
+ return FALSE;
+ }
+ umask(old);
+ if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
+ {
+ DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
+ strerror(errno));
+ }
+
+ if (listen(this->socket, 10) < 0)
+ {
+ DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno));
+ close(this->socket);
+ unlink(socket_addr.sun_path);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of stroke_socket_t.destroy
+ */
+static void destroy(private_stroke_socket_t *this)
+{
+ this->job->cancel(this->job);
+ charon->credentials->remove_set(charon->credentials, &this->ca->set);
+ charon->credentials->remove_set(charon->credentials, &this->cred->set);
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ this->cred->destroy(this->cred);
+ this->ca->destroy(this->ca);
+ this->config->destroy(this->config);
+ this->attribute->destroy(this->attribute);
+ this->control->destroy(this->control);
+ this->list->destroy(this->list);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+stroke_socket_t *stroke_socket_create()
+{
+ private_stroke_socket_t *this = malloc_thing(private_stroke_socket_t);
+
+ this->public.destroy = (void(*)(stroke_socket_t*))destroy;
+
+ if (!open_socket(this))
+ {
+ free(this);
+ return NULL;
+ }
+
+ this->cred = stroke_cred_create();
+ this->attribute = stroke_attribute_create();
+ this->ca = stroke_ca_create(this->cred);
+ this->config = stroke_config_create(this->ca, this->cred);
+ this->control = stroke_control_create();
+ this->list = stroke_list_create(this->attribute);
+
+ charon->credentials->add_set(charon->credentials, &this->ca->set);
+ charon->credentials->add_set(charon->credentials, &this->cred->set);
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+
+ this->job = callback_job_create((callback_job_cb_t)receive,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/stroke/stroke_socket.h b/src/libcharon/plugins/stroke/stroke_socket.h
new file mode 100644
index 000000000..2aac8be9b
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_socket.h
@@ -0,0 +1,42 @@
+/*
+ * 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 stroke_socket stroke_socket
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_SOCKET_H_
+#define STROKE_SOCKET_H_
+
+typedef struct stroke_socket_t stroke_socket_t;
+
+/**
+ * Stroke socket, opens UNIX communication socket, reads and dispatches.
+ */
+struct stroke_socket_t {
+
+ /**
+ * Destroy a stroke_socket instance.
+ */
+ void (*destroy)(stroke_socket_t *this);
+};
+
+/**
+ * Create a stroke_socket instance.
+ */
+stroke_socket_t *stroke_socket_create();
+
+#endif /** STROKE_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/uci/Makefile.am b/src/libcharon/plugins/uci/Makefile.am
new file mode 100644
index 000000000..6decdb9da
--- /dev/null
+++ b/src/libcharon/plugins/uci/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-uci.la
+else
+plugin_LTLIBRARIES = libstrongswan-uci.la
+endif
+
+libstrongswan_uci_la_SOURCES = \
+ uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \
+ uci_config.h uci_config.c uci_creds.h uci_creds.c \
+ uci_control.h uci_control.c
+
+libstrongswan_uci_la_LDFLAGS = -module -avoid-version
+libstrongswan_uci_la_LIBADD = -luci
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
new file mode 100644
index 000000000..c10829bb3
--- /dev/null
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -0,0 +1,592 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/uci
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_uci_la_DEPENDENCIES =
+am_libstrongswan_uci_la_OBJECTS = uci_plugin.lo uci_parser.lo \
+ uci_config.lo uci_creds.lo uci_control.lo
+libstrongswan_uci_la_OBJECTS = $(am_libstrongswan_uci_la_OBJECTS)
+libstrongswan_uci_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_uci_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_uci_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_uci_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_uci_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_uci_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-uci.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-uci.la
+libstrongswan_uci_la_SOURCES = \
+ uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \
+ uci_config.h uci_config.c uci_creds.h uci_creds.c \
+ uci_control.h uci_control.c
+
+libstrongswan_uci_la_LDFLAGS = -module -avoid-version
+libstrongswan_uci_la_LIBADD = -luci
+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/uci/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/uci/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-uci.la: $(libstrongswan_uci_la_OBJECTS) $(libstrongswan_uci_la_DEPENDENCIES)
+ $(libstrongswan_uci_la_LINK) $(am_libstrongswan_uci_la_rpath) $(libstrongswan_uci_la_OBJECTS) $(libstrongswan_uci_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_control.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
new file mode 100644
index 000000000..bd58afbf0
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * 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 "uci_config.h"
+#include "uci_parser.h"
+
+#include <daemon.h>
+
+typedef struct private_uci_config_t private_uci_config_t;
+
+/**
+ * Private data of an uci_config_t object
+ */
+struct private_uci_config_t {
+
+ /**
+ * Public part
+ */
+ uci_config_t public;
+
+ /**
+ * UCI parser context
+ */
+ uci_parser_t *parser;
+};
+
+/**
+ * enumerator implementation for create_peer_cfg_enumerator
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** currently enumerated peer config */
+ peer_cfg_t *peer_cfg;
+ /** inner uci_parser section enumerator */
+ enumerator_t *inner;
+} peer_enumerator_t;
+
+/**
+ * create a proposal from a string, with fallback to default
+ */
+static proposal_t *create_proposal(char *string, protocol_id_t proto)
+{
+ proposal_t *proposal = NULL;
+
+ if (string)
+ {
+ proposal = proposal_create_from_string(proto, string);
+ }
+ if (!proposal)
+ { /* UCI default is aes/sha1 only */
+ if (proto == PROTO_IKE)
+ {
+ proposal = proposal_create_from_string(proto,
+ "aes128-aes192-aes256-sha1-modp1536-modp2048");
+ }
+ else
+ {
+ proposal = proposal_create_from_string(proto,
+ "aes128-aes192-aes256-sha1");
+ }
+ }
+ return proposal;
+}
+
+/**
+ * create an traffic selector, fallback to dynamic
+ */
+static traffic_selector_t *create_ts(char *string)
+{
+ if (string)
+ {
+ int netbits = 32;
+ host_t *net;
+ char *pos;
+
+ string = strdupa(string);
+ pos = strchr(string, '/');
+ if (pos)
+ {
+ *pos++ = '\0';
+ netbits = atoi(pos);
+ }
+ else
+ {
+ if (strchr(string, ':'))
+ {
+ netbits = 128;
+ }
+ }
+ net = host_create_from_string(string, 0);
+ if (net)
+ {
+ return traffic_selector_create_from_subnet(net, netbits, 0, 0);
+ }
+ }
+ return traffic_selector_create_dynamic(0, 0, 65535);
+}
+
+/**
+ * create a rekey time from a string with hours, with fallback
+ */
+static u_int create_rekey(char *string)
+{
+ u_int rekey = 0;
+
+ if (string)
+ {
+ rekey = atoi(string);
+ if (rekey)
+ {
+ return rekey * 3600;
+ }
+ }
+ /* every 12 hours */
+ return 12 * 3600;
+}
+
+/**
+ * Implementation of peer_enumerator_t.public.enumerate
+ */
+static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
+{
+ char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey;
+ char *local_id, *local_addr, *local_net;
+ char *remote_id, *remote_addr, *remote_net;
+ child_cfg_t *child_cfg;
+ ike_cfg_t *ike_cfg;
+ auth_cfg_t *auth;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = create_rekey(esp_rekey) + 300,
+ .rekey = create_rekey(esp_rekey),
+ .jitter = 300
+ }
+ };
+
+ /* defaults */
+ name = "unnamed";
+ local_id = NULL;
+ remote_id = NULL;
+ local_addr = "0.0.0.0";
+ remote_addr = "0.0.0.0";
+ local_net = NULL;
+ remote_net = NULL;
+ ike_proposal = NULL;
+ esp_proposal = NULL;
+ ike_rekey = NULL;
+ esp_rekey = NULL;
+
+ if (this->inner->enumerate(this->inner, &name, &local_id, &remote_id,
+ &local_addr, &remote_addr, &local_net, &remote_net,
+ &ike_proposal, &esp_proposal, &ike_rekey, &esp_rekey))
+ {
+ DESTROY_IF(this->peer_cfg);
+ ike_cfg = ike_cfg_create(FALSE, FALSE,
+ local_addr, IKEV2_UDP_PORT, remote_addr, IKEV2_UDP_PORT);
+ ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
+ this->peer_cfg = peer_cfg_create(
+ name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
+ 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
+ 1800, 900, /* jitter, overtime */
+ TRUE, 60, /* mobike, dpddelay */
+ NULL, NULL, /* vip, pool */
+ FALSE, NULL, NULL); /* mediation, med by, peer id */
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_string(local_id));
+ this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, TRUE);
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ if (remote_id)
+ {
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_string(remote_id));
+ }
+ this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
+
+ child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
+ child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
+ child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
+ this->peer_cfg->add_child_cfg(this->peer_cfg, child_cfg);
+ *cfg = this->peer_cfg;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of peer_enumerator_t.public.destroy
+ */
+static void peer_enumerator_destroy(peer_enumerator_t *this)
+{
+ DESTROY_IF(this->peer_cfg);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_uci_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
+
+ e->public.enumerate = (void*)peer_enumerator_enumerate;
+ e->public.destroy = (void*)peer_enumerator_destroy;
+ e->peer_cfg = NULL;
+ e->inner = this->parser->create_section_enumerator(this->parser,
+ "local_id", "remote_id", "local_addr", "remote_addr",
+ "local_net", "remote_net", "ike_proposal", "esp_proposal",
+ "ike_rekey", "esp_rekey", NULL);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * enumerator implementation for create_ike_cfg_enumerator
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** currently enumerated ike config */
+ ike_cfg_t *ike_cfg;
+ /** inner uci_parser section enumerator */
+ enumerator_t *inner;
+} ike_enumerator_t;
+
+/**
+ * Implementation of peer_enumerator_t.public.enumerate
+ */
+static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
+{
+ char *local_addr, *remote_addr, *ike_proposal;
+
+ /* defaults */
+ local_addr = "0.0.0.0";
+ remote_addr = "0.0.0.0";
+ ike_proposal = NULL;
+
+ if (this->inner->enumerate(this->inner, NULL,
+ &local_addr, &remote_addr, &ike_proposal))
+ {
+ DESTROY_IF(this->ike_cfg);
+ this->ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, IKEV2_UDP_PORT,
+ remote_addr, IKEV2_UDP_PORT);
+ this->ike_cfg->add_proposal(this->ike_cfg,
+ create_proposal(ike_proposal, PROTO_IKE));
+
+ *cfg = this->ike_cfg;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of ike_enumerator_t.public.destroy
+ */
+static void ike_enumerator_destroy(ike_enumerator_t *this)
+{
+ DESTROY_IF(this->ike_cfg);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_uci_config_t *this,
+ host_t *me, host_t *other)
+{
+ ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
+
+ e->public.enumerate = (void*)ike_enumerator_enumerate;
+ e->public.destroy = (void*)ike_enumerator_destroy;
+ e->ike_cfg = NULL;
+ e->inner = this->parser->create_section_enumerator(this->parser,
+ "local_addr", "remote_addr", "ike_proposal", NULL);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_uci_config_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *current, *found = NULL;
+
+ enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
+ if (enumerator)
+ {
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(name, current->get_name(current)))
+ {
+ found = current->get_ref(current);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found;
+}
+
+/**
+ * Implementation of uci_config_t.destroy.
+ */
+static void destroy(private_uci_config_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+uci_config_t *uci_config_create(uci_parser_t *parser)
+{
+ private_uci_config_t *this = malloc_thing(private_uci_config_t);
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(uci_config_t*))destroy;
+ this->parser = parser;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/uci/uci_config.h b/src/libcharon/plugins/uci/uci_config.h
new file mode 100644
index 000000000..130f15d85
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_config.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 uci_config_t uci_config
+ * @{ @ingroup uci
+ */
+
+#ifndef UCI_CONFIG_H_
+#define UCI_CONFIG_H_
+
+#include "uci_parser.h"
+
+#include <config/backend.h>
+
+typedef struct uci_config_t uci_config_t;
+
+/**
+ * OpenWRT UCI configuration backend.
+ */
+struct uci_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(uci_config_t *this);
+};
+
+/**
+ * Create a UCI based configuration backend.
+ *
+ * @param parser UCI parser to use
+ * @return configuration backend
+ */
+uci_config_t *uci_config_create(uci_parser_t *parser);
+
+#endif /** UCI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c
new file mode 100644
index 000000000..3c4928be4
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_control.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "uci_control.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <processing/jobs/callback_job.h>
+
+#define FIFO_FILE "/var/run/charon.fifo"
+
+
+typedef struct private_uci_control_t private_uci_control_t;
+
+/**
+ * private data of uci_control_t
+ */
+struct private_uci_control_t {
+
+ /**
+ * Public part
+ */
+ uci_control_t public;
+
+ /**
+ * Job
+ */
+ callback_job_t *job;
+};
+
+/**
+ * write answer to fifo
+ */
+static void write_fifo(private_uci_control_t *this, char *format, ...)
+{
+ va_list args;
+ FILE *out;
+
+ out = fopen(FIFO_FILE, "w");
+ if (out)
+ {
+ va_start(args, format);
+ vfprintf(out, format, args);
+ va_end(args);
+ fclose(out);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "writing to UCI fifo failed: %s", strerror(errno));
+ }
+}
+
+/**
+ * print IKE_SA status information
+ */
+static void status(private_uci_control_t *this, char *name)
+{
+ enumerator_t *configs, *sas;
+ iterator_t *children;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ peer_cfg_t *peer_cfg;
+ char buf[2048];
+ FILE *out = NULL;
+
+ configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL);
+ while (configs->enumerate(configs, &peer_cfg))
+ {
+ if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
+ {
+ continue;
+ }
+ sas = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (sas->enumerate(sas, &ike_sa))
+ {
+ if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg)))
+ {
+ continue;
+ }
+ if (!out)
+ {
+ out = fmemopen(buf, sizeof(buf), "w");
+ if (!out)
+ {
+ continue;
+ }
+ }
+ fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
+ ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
+
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ fprintf(out, "%#R",
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
+ children->destroy(children);
+ fprintf(out, "\n");
+ }
+ sas->destroy(sas);
+ }
+ configs->destroy(configs);
+ if (out)
+ {
+ fclose(out);
+ write_fifo(this, "%s", buf);
+ }
+ else
+ {
+ write_fifo(this, "");
+ }
+}
+
+/**
+ * Initiate an IKE_SA
+ */
+static void initiate(private_uci_control_t *this, char *name)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ enumerator_t *enumerator;
+
+ peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ if (enumerator->enumerate(enumerator, &child_cfg) &&
+ charon->controller->initiate(charon->controller, peer_cfg,
+ child_cfg->get_ref(child_cfg),
+ controller_cb_empty, NULL) == SUCCESS)
+ {
+ write_fifo(this, "connection '%s' established\n", name);
+ }
+ else
+ {
+ write_fifo(this, "establishing connection '%s' failed\n", name);
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ write_fifo(this, "no connection named '%s' found\n", name);
+ }
+}
+
+/**
+ * terminate an IKE_SA
+ */
+static void terminate(private_uci_control_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ u_int id;
+
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (streq(name, ike_sa->get_name(ike_sa)))
+ {
+ id = ike_sa->get_unique_id(ike_sa);
+ enumerator->destroy(enumerator);
+ charon->controller->terminate_ike(charon->controller, id,
+ controller_cb_empty, NULL);
+ write_fifo(this, "connection '%s' terminated\n", name);
+ return;
+ }
+ }
+ enumerator->destroy(enumerator);
+ write_fifo(this, "no active connection named '%s'\n", name);
+}
+
+/**
+ * dispatch control request
+ */
+static void process(private_uci_control_t *this, char *message)
+{
+ enumerator_t* enumerator;
+
+ enumerator = enumerator_create_token(message, " \n", "");
+ if (enumerator->enumerate(enumerator, &message))
+ {
+ if (streq(message, "status"))
+ {
+ if (enumerator->enumerate(enumerator, &message))
+ {
+ status(this, message);
+ }
+ else
+ {
+ status(this, NULL);
+ }
+ }
+ else if (streq(message, "up") &&
+ enumerator->enumerate(enumerator, &message))
+ {
+ initiate(this, message);
+ }
+ else if (streq(message, "down") &&
+ enumerator->enumerate(enumerator, &message))
+ {
+ terminate(this, message);
+ }
+ else
+ {
+ write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
+ " status format: name peer-id peer-addr tunnel(s)\n");
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * read from fifo
+ */
+static job_requeue_t receive(private_uci_control_t *this)
+{
+ char message[128];
+ int len;
+ bool oldstate;
+ FILE *in;
+
+ memset(message, 0, sizeof(message));
+ oldstate = thread_cancelability(TRUE);
+ in = fopen(FIFO_FILE, "r");
+ thread_cancelability(oldstate);
+ if (in)
+ {
+ len = fread(message, 1, sizeof(message) - 1, in);
+ fclose(in);
+ if (len > 0)
+ {
+ process(this, message);
+ }
+ else
+ {
+ DBG1(DBG_DMN, "reading from UCI fifo failed: %s", strerror(errno));
+ }
+ }
+ else
+ {
+ DBG1(DBG_DMN, "opening UCI fifo failed: %s", strerror(errno));
+ }
+ return JOB_REQUEUE_FAIR;
+}
+
+/**
+ * Implementation of uci_control_t.destroy
+ */
+static void destroy(private_uci_control_t *this)
+{
+ this->job->cancel(this->job);
+ unlink(FIFO_FILE);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+uci_control_t *uci_control_create()
+{
+ private_uci_control_t *this = malloc_thing(private_uci_control_t);
+
+ this->public.destroy = (void(*)(uci_control_t*))destroy;
+
+ unlink(FIFO_FILE);
+ if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
+ {
+ DBG1(DBG_CFG, "creating UCI control fifo '%s' failed: %s",
+ FIFO_FILE, strerror(errno));
+ }
+ else
+ {
+ this->job = callback_job_create((callback_job_cb_t)receive,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+ }
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/uci/uci_control.h b/src/libcharon/plugins/uci/uci_control.h
new file mode 100644
index 000000000..794220aa1
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_control.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 uci_control_t uci_control
+ * @{ @ingroup uci
+ */
+
+#ifndef UCI_CONTROL_H_
+#define UCI_CONTROL_H_
+
+typedef struct uci_control_t uci_control_t;
+
+/**
+ * UCI control interface, uses a simple FIFO file
+ */
+struct uci_control_t {
+
+ /**
+ * Destroy the controller
+ */
+ void (*destroy)(uci_control_t *this);
+};
+
+/**
+ * Create a UCI based configuration backend.
+ */
+uci_control_t *uci_control_create();
+
+#endif /** UCI_CONTROL_H_ @}*/
diff --git a/src/libcharon/plugins/uci/uci_creds.c b/src/libcharon/plugins/uci/uci_creds.c
new file mode 100644
index 000000000..4d664feb2
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_creds.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * Copyright (C) 2008 Martin Willi
+ * 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 "uci_creds.h"
+
+#include <daemon.h>
+#include <credentials/keys/shared_key.h>
+#include <utils/identification.h>
+
+typedef struct private_uci_creds_t private_uci_creds_t;
+
+/**
+ * Private data of an uci_creds_t object
+ */
+struct private_uci_creds_t {
+ /**
+ * Public part
+ */
+ uci_creds_t public;
+
+ /**
+ * UCI parser context
+ */
+ uci_parser_t *parser;
+};
+
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** inneer UCI enumerator */
+ enumerator_t *inner;
+ /** currently enumerated shared shared */
+ shared_key_t *current;
+ /** local ID to match */
+ identification_t *me;
+ /** remote ID to match */
+ identification_t *other;
+} shared_enumerator_t;
+
+/**
+ * Implementation of shared_enumerator_t.public.enumerate
+ */
+static bool shared_enumerator_enumerate(shared_enumerator_t *this,
+ shared_key_t **key, id_match_t *me, id_match_t *other)
+{
+ char *local_id, *remote_id, *psk;
+ identification_t *local, *remote;
+
+ while (TRUE)
+ {
+ /* defaults */
+ local_id = "%any";
+ remote_id = "%any";
+ psk = NULL;
+
+ if (!this->inner->enumerate(this->inner, NULL,
+ &local_id, &remote_id, &psk))
+ {
+ return FALSE;
+ }
+ if (psk == NULL)
+ {
+ continue;
+ }
+ if (me)
+ {
+ local = identification_create_from_string(local_id);
+ *me = this->me ? this->me->matches(this->me, local)
+ : ID_MATCH_ANY;
+ local->destroy(local);
+ if (!*me)
+ {
+ continue;
+ }
+ }
+ if (other)
+ {
+ remote = identification_create_from_string(remote_id);
+ *other = this->other ? this->other->matches(this->other, remote)
+ : ID_MATCH_ANY;
+ remote->destroy(remote);
+ if (!*other)
+ {
+ continue;
+ }
+ }
+ break;
+ }
+ DESTROY_IF(this->current);
+ this->current = shared_key_create(SHARED_IKE,
+ chunk_clone(chunk_create(psk, strlen(psk))));
+ *key = this->current;
+ return TRUE;
+}
+
+/**
+ * Implementation of shared_enumerator_t.public.destroy
+ */
+static void shared_enumerator_destroy(shared_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ DESTROY_IF(this->current);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_shared_cfg_enumerator.
+ */
+static enumerator_t* create_shared_enumerator(private_uci_creds_t *this,
+ shared_key_type_t type,
+ identification_t *me,
+ identification_t *other)
+{
+ shared_enumerator_t *e;
+
+ if (type != SHARED_IKE)
+ {
+ return NULL;
+ }
+
+ e = malloc_thing(shared_enumerator_t);
+ e->current = NULL;
+ e->public.enumerate = (void*)shared_enumerator_enumerate;
+ e->public.destroy = (void*)shared_enumerator_destroy;
+ e->me = me;
+ e->other = other;
+ e->inner = this->parser->create_section_enumerator(this->parser,
+ "local_id", "remote_id", "psk", NULL);
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of uci_creds_t.destroy
+ */
+static void destroy(private_uci_creds_t *this)
+{
+ free(this);
+}
+
+uci_creds_t *uci_creds_create(uci_parser_t *parser)
+{
+ private_uci_creds_t *this = malloc_thing(private_uci_creds_t);
+
+ this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))create_shared_enumerator;
+ this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))return_null;
+ this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))return_null;
+ this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null;
+ this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop;
+ this->public.destroy = (void(*) (uci_creds_t*))destroy;
+
+ this->parser = parser;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/uci/uci_creds.h b/src/libcharon/plugins/uci/uci_creds.h
new file mode 100644
index 000000000..a283ed9f5
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_creds.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 uci_creds_t uci_creds
+ * @{ @ingroup uci
+ */
+
+#ifndef UCI_CREDS_H_
+#define UCI_CREDS_H_
+
+#include "uci_parser.h"
+
+#include <credentials/credential_set.h>
+
+typedef struct uci_creds_t uci_creds_t;
+
+/**
+ * OpenWRT UCI credential set implementation.
+ */
+struct uci_creds_t {
+
+ /**
+ * Implements credential set interface.
+ */
+ credential_set_t credential_set;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(uci_creds_t *this);
+};
+
+/**
+ * Create a UCI based credential set.
+ *
+ * @param parser UCI parser to use
+ * @return credential set
+ */
+uci_creds_t *uci_creds_create(uci_parser_t *parser);
+
+#endif /** UCI_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/uci/uci_parser.c b/src/libcharon/plugins/uci/uci_parser.c
new file mode 100644
index 000000000..6de55d218
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_parser.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 "uci_parser.h"
+
+#include <stdarg.h>
+
+#include <library.h>
+#include <uci.h>
+
+typedef struct private_uci_parser_t private_uci_parser_t;
+
+/**
+ * Private data of an uci_parser_t object
+ */
+struct private_uci_parser_t {
+
+ /**
+ * Public part
+ */
+ uci_parser_t public;
+
+ /**
+ * UCI package name this parser reads
+ */
+ char *package;
+};
+
+/**
+ * enumerator implementation create_section_enumerator
+ */
+typedef struct {
+ /** implements enumerator */
+ enumerator_t public;
+ /** currently enumerated uci section */
+ struct uci_element *current;
+ /** all uci ipsec config sections */
+ struct uci_list *list;
+ /** uci conntext */
+ struct uci_context *ctx;
+ /** ipsec uci package */
+ struct uci_package *package;
+ /** NULL terminated list of keywords */
+ char *keywords[];
+} section_enumerator_t;
+
+/**
+ * Implementation of section_enumerator_t.enumerate
+ */
+static bool section_enumerator_enumerate(section_enumerator_t *this, ...)
+{
+ struct uci_element *element;
+ char **value;
+ va_list args;
+ int i;
+
+ if (&this->current->list == this->list)
+ {
+ return FALSE;
+ }
+
+ va_start(args, this);
+
+ value = va_arg(args, char**);
+ if (value)
+ {
+ if (uci_lookup(this->ctx, &element, this->package,
+ this->current->name, "name") == UCI_OK)
+ { /* use "name" attribute as config name if available ... */
+ *value = uci_to_option(element)->value;
+ }
+ else
+ { /* ... or the section name becomes config name */
+ *value = uci_to_section(this->current)->type;
+ }
+ }
+
+ /* followed by keyword parameters */
+ for (i = 0; this->keywords[i]; i++)
+ {
+ value = va_arg(args, char**);
+ if (value && uci_lookup(this->ctx, &element, this->package,
+ this->current->name, this->keywords[i]) == UCI_OK)
+ {
+ *value = uci_to_option(element)->value;
+ }
+ }
+ va_end(args);
+
+ this->current = list_to_element(this->current->list.next);
+ return TRUE;
+}
+
+/**
+ * Implementation of section_enumerator_t.public.destroy
+ */
+static void section_enumerator_destroy(section_enumerator_t *this)
+{
+ uci_free_context(this->ctx);
+ free(this);
+}
+
+/**
+ * Implementation of backend_t.create_section_enumerator.
+ */
+static enumerator_t* create_section_enumerator(private_uci_parser_t *this, ...)
+{
+ section_enumerator_t *e;
+ va_list args;
+ int i;
+
+ /* allocate enumerator large enought to hold keyword pointers */
+ i = 1;
+ va_start(args, this);
+ while (va_arg(args, char*))
+ {
+ i++;
+ }
+ va_end(args);
+ e = malloc(sizeof(section_enumerator_t) + sizeof(char*) * i);
+ i = 0;
+ va_start(args, this);
+ do
+ {
+ e->keywords[i] = va_arg(args, char*);
+ }
+ while (e->keywords[i++]);
+ va_end(args);
+
+ e->public.enumerate = (void*)section_enumerator_enumerate;
+ e->public.destroy = (void*)section_enumerator_destroy;
+
+ /* load uci context */
+ e->ctx = uci_alloc_context();
+ if (uci_load(e->ctx, this->package, &e->package) != UCI_OK)
+ {
+ section_enumerator_destroy(e);
+ return NULL;
+ }
+ e->list = &e->package->sections;
+ e->current = list_to_element(e->list->next);
+ if (e->current->type != UCI_TYPE_SECTION)
+ {
+ section_enumerator_destroy(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+/**
+ * Implementation of uci_parser_t.destroy.
+ */
+static void destroy(private_uci_parser_t *this)
+{
+ free(this->package);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+uci_parser_t *uci_parser_create(char *package)
+{
+ private_uci_parser_t *this = malloc_thing(private_uci_parser_t);
+
+ this->public.create_section_enumerator = (enumerator_t*(*)(uci_parser_t*, ...))create_section_enumerator;
+ this->public.destroy = (void(*)(uci_parser_t*))destroy;
+
+ this->package = strdup(package);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/uci/uci_parser.h b/src/libcharon/plugins/uci/uci_parser.h
new file mode 100644
index 000000000..7217e507a
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_parser.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 uci_parser_t uci_parser
+ * @{ @ingroup uci
+ */
+
+#ifndef UCI_PARSER_H_
+#define UCI_PARSER_H_
+
+#include <utils/enumerator.h>
+
+typedef struct uci_parser_t uci_parser_t;
+
+/**
+ * Wrapper to parse UCI sections with an enumerator.
+ */
+struct uci_parser_t {
+
+ /**
+ * Create an enumerator over a section.
+ *
+ * The enumerator returns a section name followed by values for the keywords
+ * specified in the variable argument list of this function.
+ *
+ * @param ... variable argument list with keywords, NULL terminated
+ * @return enumerator over sections
+ */
+ enumerator_t* (*create_section_enumerator)(uci_parser_t *this, ...);
+
+ /**
+ * Destroy the parser.
+ */
+ void (*destroy)(uci_parser_t *this);
+};
+
+/**
+ * Create a UCI parser.
+ *
+ * @param package UCI package this parser should read
+ * @return parser context
+ */
+uci_parser_t *uci_parser_create(char *package);
+
+#endif /** UCI_PARSER_H_ @}*/
diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c
new file mode 100644
index 000000000..742fcf4d0
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_plugin.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 "uci_plugin.h"
+#include "uci_config.h"
+#include "uci_creds.h"
+#include "uci_control.h"
+
+#include <daemon.h>
+
+/**
+ * UCI package name to use for lookups
+ */
+#define UCI_PACKAGE "strongswan"
+
+typedef struct private_uci_plugin_t private_uci_plugin_t;
+
+/**
+ * private data of uci plugin
+ */
+struct private_uci_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ uci_plugin_t public;
+
+ /**
+ * UCI configuration backend
+ */
+ uci_config_t *config;
+
+ /**
+ * UCI credential set implementation
+ */
+ uci_creds_t *creds;
+
+ /**
+ * UCI parser wrapper
+ */
+ uci_parser_t *parser;
+
+ /**
+ * UCI control interface
+ */
+ uci_control_t *control;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_uci_plugin_t *this)
+{
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->creds->credential_set);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->parser->destroy(this->parser);
+ this->control->destroy(this->control);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *uci_plugin_create()
+{
+ private_uci_plugin_t *this = malloc_thing(private_uci_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->parser = uci_parser_create(UCI_PACKAGE);
+ this->config = uci_config_create(this->parser);
+ this->creds = uci_creds_create(this->parser);
+ this->control = uci_control_create();
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/uci/uci_plugin.h b/src/libcharon/plugins/uci/uci_plugin.h
new file mode 100644
index 000000000..980ab26fd
--- /dev/null
+++ b/src/libcharon/plugins/uci/uci_plugin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 Thomas Kallenberg
+ * 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 uci uci
+ * @ingroup cplugins
+ *
+ * @defgroup uci_plugin uci_plugin
+ * @{ @ingroup uci
+ */
+
+#ifndef UCI_PLUGIN_H_
+#define UCI_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct uci_plugin_t uci_plugin_t;
+
+/**
+ * OpenWRT UCI (Unified Configuration Interface) configuration plugin.
+ */
+struct uci_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** UCI_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am
new file mode 100644
index 000000000..e27d1f859
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/Makefile.am
@@ -0,0 +1,29 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-unit-tester.la
+else
+plugin_LTLIBRARIES = libstrongswan-unit-tester.la
+endif
+
+libstrongswan_unit_tester_la_SOURCES = \
+ unit_tester.c unit_tester.h tests.h \
+ tests/test_enumerator.c \
+ tests/test_auth_info.c \
+ tests/test_curl.c \
+ tests/test_mysql.c \
+ tests/test_sqlite.c \
+ tests/test_mutex.c \
+ tests/test_rsa_gen.c \
+ tests/test_cert.c \
+ tests/test_med_db.c \
+ tests/test_chunk.c \
+ tests/test_pool.c \
+ tests/test_agent.c \
+ tests/test_id.c
+
+libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
new file mode 100644
index 000000000..6ca43a38f
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -0,0 +1,708 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/unit_tester
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_unit_tester_la_LIBADD =
+am_libstrongswan_unit_tester_la_OBJECTS = unit_tester.lo \
+ test_enumerator.lo test_auth_info.lo test_curl.lo \
+ test_mysql.lo test_sqlite.lo test_mutex.lo test_rsa_gen.lo \
+ test_cert.lo test_med_db.lo test_chunk.lo test_pool.lo \
+ test_agent.lo test_id.lo
+libstrongswan_unit_tester_la_OBJECTS = \
+ $(am_libstrongswan_unit_tester_la_OBJECTS)
+libstrongswan_unit_tester_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_unit_tester_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_unit_tester_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_unit_tester_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_unit_tester_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_unit_tester_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-unit-tester.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-unit-tester.la
+libstrongswan_unit_tester_la_SOURCES = \
+ unit_tester.c unit_tester.h tests.h \
+ tests/test_enumerator.c \
+ tests/test_auth_info.c \
+ tests/test_curl.c \
+ tests/test_mysql.c \
+ tests/test_sqlite.c \
+ tests/test_mutex.c \
+ tests/test_rsa_gen.c \
+ tests/test_cert.c \
+ tests/test_med_db.c \
+ tests/test_chunk.c \
+ tests/test_pool.c \
+ tests/test_agent.c \
+ tests/test_id.c
+
+libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/unit_tester/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/unit_tester/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-unit-tester.la: $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_DEPENDENCIES)
+ $(libstrongswan_unit_tester_la_LINK) $(am_libstrongswan_unit_tester_la_rpath) $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_agent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auth_info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_chunk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_curl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_enumerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_id.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_med_db.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mutex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mysql.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_rsa_gen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sqlite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_tester.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+test_enumerator.lo: tests/test_enumerator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_enumerator.lo -MD -MP -MF $(DEPDIR)/test_enumerator.Tpo -c -o test_enumerator.lo `test -f 'tests/test_enumerator.c' || echo '$(srcdir)/'`tests/test_enumerator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_enumerator.Tpo $(DEPDIR)/test_enumerator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_enumerator.c' object='test_enumerator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_enumerator.lo `test -f 'tests/test_enumerator.c' || echo '$(srcdir)/'`tests/test_enumerator.c
+
+test_auth_info.lo: tests/test_auth_info.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_auth_info.lo -MD -MP -MF $(DEPDIR)/test_auth_info.Tpo -c -o test_auth_info.lo `test -f 'tests/test_auth_info.c' || echo '$(srcdir)/'`tests/test_auth_info.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_auth_info.Tpo $(DEPDIR)/test_auth_info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_auth_info.c' object='test_auth_info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_auth_info.lo `test -f 'tests/test_auth_info.c' || echo '$(srcdir)/'`tests/test_auth_info.c
+
+test_curl.lo: tests/test_curl.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_curl.lo -MD -MP -MF $(DEPDIR)/test_curl.Tpo -c -o test_curl.lo `test -f 'tests/test_curl.c' || echo '$(srcdir)/'`tests/test_curl.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_curl.Tpo $(DEPDIR)/test_curl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_curl.c' object='test_curl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_curl.lo `test -f 'tests/test_curl.c' || echo '$(srcdir)/'`tests/test_curl.c
+
+test_mysql.lo: tests/test_mysql.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_mysql.lo -MD -MP -MF $(DEPDIR)/test_mysql.Tpo -c -o test_mysql.lo `test -f 'tests/test_mysql.c' || echo '$(srcdir)/'`tests/test_mysql.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_mysql.Tpo $(DEPDIR)/test_mysql.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_mysql.c' object='test_mysql.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_mysql.lo `test -f 'tests/test_mysql.c' || echo '$(srcdir)/'`tests/test_mysql.c
+
+test_sqlite.lo: tests/test_sqlite.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_sqlite.lo -MD -MP -MF $(DEPDIR)/test_sqlite.Tpo -c -o test_sqlite.lo `test -f 'tests/test_sqlite.c' || echo '$(srcdir)/'`tests/test_sqlite.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_sqlite.Tpo $(DEPDIR)/test_sqlite.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_sqlite.c' object='test_sqlite.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_sqlite.lo `test -f 'tests/test_sqlite.c' || echo '$(srcdir)/'`tests/test_sqlite.c
+
+test_mutex.lo: tests/test_mutex.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_mutex.lo -MD -MP -MF $(DEPDIR)/test_mutex.Tpo -c -o test_mutex.lo `test -f 'tests/test_mutex.c' || echo '$(srcdir)/'`tests/test_mutex.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_mutex.Tpo $(DEPDIR)/test_mutex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_mutex.c' object='test_mutex.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_mutex.lo `test -f 'tests/test_mutex.c' || echo '$(srcdir)/'`tests/test_mutex.c
+
+test_rsa_gen.lo: tests/test_rsa_gen.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_rsa_gen.lo -MD -MP -MF $(DEPDIR)/test_rsa_gen.Tpo -c -o test_rsa_gen.lo `test -f 'tests/test_rsa_gen.c' || echo '$(srcdir)/'`tests/test_rsa_gen.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_rsa_gen.Tpo $(DEPDIR)/test_rsa_gen.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_rsa_gen.c' object='test_rsa_gen.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_rsa_gen.lo `test -f 'tests/test_rsa_gen.c' || echo '$(srcdir)/'`tests/test_rsa_gen.c
+
+test_cert.lo: tests/test_cert.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cert.lo -MD -MP -MF $(DEPDIR)/test_cert.Tpo -c -o test_cert.lo `test -f 'tests/test_cert.c' || echo '$(srcdir)/'`tests/test_cert.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_cert.Tpo $(DEPDIR)/test_cert.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_cert.c' object='test_cert.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cert.lo `test -f 'tests/test_cert.c' || echo '$(srcdir)/'`tests/test_cert.c
+
+test_med_db.lo: tests/test_med_db.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_med_db.lo -MD -MP -MF $(DEPDIR)/test_med_db.Tpo -c -o test_med_db.lo `test -f 'tests/test_med_db.c' || echo '$(srcdir)/'`tests/test_med_db.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_med_db.Tpo $(DEPDIR)/test_med_db.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_med_db.c' object='test_med_db.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_med_db.lo `test -f 'tests/test_med_db.c' || echo '$(srcdir)/'`tests/test_med_db.c
+
+test_chunk.lo: tests/test_chunk.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_chunk.lo -MD -MP -MF $(DEPDIR)/test_chunk.Tpo -c -o test_chunk.lo `test -f 'tests/test_chunk.c' || echo '$(srcdir)/'`tests/test_chunk.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_chunk.Tpo $(DEPDIR)/test_chunk.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_chunk.c' object='test_chunk.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_chunk.lo `test -f 'tests/test_chunk.c' || echo '$(srcdir)/'`tests/test_chunk.c
+
+test_pool.lo: tests/test_pool.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_pool.lo -MD -MP -MF $(DEPDIR)/test_pool.Tpo -c -o test_pool.lo `test -f 'tests/test_pool.c' || echo '$(srcdir)/'`tests/test_pool.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_pool.Tpo $(DEPDIR)/test_pool.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_pool.c' object='test_pool.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_pool.lo `test -f 'tests/test_pool.c' || echo '$(srcdir)/'`tests/test_pool.c
+
+test_agent.lo: tests/test_agent.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_agent.lo -MD -MP -MF $(DEPDIR)/test_agent.Tpo -c -o test_agent.lo `test -f 'tests/test_agent.c' || echo '$(srcdir)/'`tests/test_agent.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_agent.Tpo $(DEPDIR)/test_agent.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_agent.c' object='test_agent.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_agent.lo `test -f 'tests/test_agent.c' || echo '$(srcdir)/'`tests/test_agent.c
+
+test_id.lo: tests/test_id.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_id.lo -MD -MP -MF $(DEPDIR)/test_id.Tpo -c -o test_id.lo `test -f 'tests/test_id.c' || echo '$(srcdir)/'`tests/test_id.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_id.Tpo $(DEPDIR)/test_id.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_id.c' object='test_id.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_id.lo `test -f 'tests/test_id.c' || echo '$(srcdir)/'`tests/test_id.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/unit_tester/tests.h b/src/libcharon/plugins/unit_tester/tests.h
new file mode 100644
index 000000000..96313d390
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tests tests
+ * @{ @ingroup unit_tester
+ */
+
+DEFINE_TEST("linked_list_t->remove()", test_list_remove, FALSE)
+DEFINE_TEST("simple enumerator", test_enumerate, FALSE)
+DEFINE_TEST("nested enumerator", test_enumerate_nested, FALSE)
+DEFINE_TEST("filtered enumerator", test_enumerate_filtered, FALSE)
+DEFINE_TEST("token enumerator", test_enumerate_token, FALSE)
+DEFINE_TEST("auth cfg", test_auth_cfg, FALSE)
+DEFINE_TEST("CURL get", test_curl_get, FALSE)
+DEFINE_TEST("MySQL operations", test_mysql, FALSE)
+DEFINE_TEST("SQLite operations", test_sqlite, FALSE)
+DEFINE_TEST("mutex primitive", test_mutex, FALSE)
+DEFINE_TEST("RSA key generation", test_rsa_gen, FALSE)
+DEFINE_TEST("RSA subjectPublicKeyInfo loading", test_rsa_load_any, FALSE)
+DEFINE_TEST("X509 certificate", test_cert_x509, FALSE)
+DEFINE_TEST("Mediation database key fetch", test_med_db, FALSE)
+DEFINE_TEST("Base64 converter", test_chunk_base64, FALSE)
+DEFINE_TEST("IP pool", test_pool, FALSE)
+DEFINE_TEST("SSH agent", test_agent, FALSE)
+DEFINE_TEST("ID parts", test_id_parts, FALSE)
+DEFINE_TEST("ID wildcards", test_id_wildcards, FALSE)
+DEFINE_TEST("ID equals", test_id_equals, FALSE)
+DEFINE_TEST("ID matches", test_id_matches, FALSE)
+
+/** @}*/
diff --git a/src/libcharon/plugins/unit_tester/tests/test_agent.c b/src/libcharon/plugins/unit_tester/tests/test_agent.c
new file mode 100644
index 000000000..baab629be
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_agent.c
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+
+/*******************************************************************************
+ * SSH agent signature creation and verification
+ ******************************************************************************/
+bool test_agent()
+{
+ char *path;
+ chunk_t sig, data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08);
+ private_key_t *private;
+ public_key_t *public;
+
+ path = getenv("SSH_AUTH_SOCK");
+ if (!path)
+ {
+ DBG1(DBG_CFG, "ssh-agent not found.");
+ return FALSE;
+ }
+
+ private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_AGENT_SOCKET, path, BUILD_END);
+ if (!private)
+ {
+ return FALSE;
+ }
+ if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_SHA1, data, &sig))
+ {
+ return FALSE;
+ }
+ public = private->get_public_key(private);
+ if (!public)
+ {
+ return FALSE;;
+ }
+ if (!public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig))
+ {
+ return FALSE;
+ }
+ free(sig.ptr);
+ data.ptr[1] = 0x01; /* fake it */
+ if (public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig))
+ {
+ return FALSE;
+ }
+
+ private->destroy(private);
+ public->destroy(public);
+
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c
new file mode 100644
index 000000000..d6abe7a05
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <daemon.h>
+#include <library.h>
+#include <config/auth_cfg.h>
+
+
+static chunk_t certchunk = chunk_from_chars(
+ 0x30,0x82,0x02,0xfa,0x30,0x82,0x01,0xe2,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x5a,
+ 0xf2,0x65,0xae,0x78,0xff,0x23,0xde,0xf7,0xa6,0xa3,0x94,0x8c,0x3f,0xa0,0xc1,0x30,
+ 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x39,
+ 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,
+ 0x17,0x06,0x03,0x55,0x04,0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,
+ 0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,
+ 0x03,0x13,0x06,0x6d,0x61,0x72,0x74,0x69,0x6e,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,
+ 0x34,0x32,0x37,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x17,0x0d,0x31,0x32,0x30,0x34,
+ 0x32,0x35,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x30,0x39,0x31,0x0b,0x30,0x09,0x06,
+ 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,
+ 0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,
+ 0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x03,0x13,0x06,0x6d,0x61,
+ 0x72,0x74,0x69,0x6e,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
+ 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,
+ 0x02,0x82,0x01,0x01,0x00,0xd7,0xb9,0xba,0x4d,0xe2,0x3b,0x3d,0x35,0x7a,0x3f,0x88,
+ 0x67,0x95,0xe7,0xfd,0x9f,0xe9,0x0a,0x0d,0x79,0x3a,0x9e,0x21,0x8f,0xcb,0xe4,0x67,
+ 0x24,0xae,0x0c,0xda,0xb3,0xcc,0xec,0x36,0xb4,0xa8,0x4d,0xf1,0x3d,0xad,0xe4,0x8c,
+ 0x63,0x92,0x54,0xb7,0xb2,0x02,0xa2,0x00,0x62,0x8b,0x04,0xac,0xa0,0x17,0xad,0x17,
+ 0x9a,0x05,0x0d,0xd7,0xb3,0x08,0x02,0xc5,0x26,0xcf,0xdd,0x05,0x42,0xfc,0x13,0x6d,
+ 0x9f,0xb1,0xf3,0x4f,0x82,0x1d,0xef,0x01,0xc9,0x91,0xea,0x37,0x1b,0x79,0x28,0xfa,
+ 0xbf,0x9f,0xb3,0xeb,0x82,0x4f,0x10,0xc6,0x4b,0xa4,0x08,0xf7,0x8e,0xf2,0x00,0xea,
+ 0x04,0x97,0x80,0x9f,0x65,0x86,0xde,0x6b,0xc7,0xda,0x83,0xfc,0xad,0x4a,0xaf,0x52,
+ 0x8b,0x4d,0x33,0xee,0x49,0x87,0x2f,0x3b,0x60,0x45,0x66,0x8f,0xe6,0x89,0xcc,0xb1,
+ 0x92,0x02,0x17,0x2b,0x7b,0x8e,0x90,0x47,0x84,0x84,0x59,0x95,0x81,0xd8,0xe0,0xf3,
+ 0x87,0xe0,0x04,0x09,0xfd,0xcc,0x3a,0x21,0x34,0xfa,0xec,0xbe,0xf5,0x9c,0xcf,0x55,
+ 0x80,0x7b,0xe3,0x75,0x9d,0x36,0x68,0xab,0x83,0xe3,0xad,0x01,0x53,0x0d,0x8a,0x9a,
+ 0xa6,0xb0,0x15,0xc9,0xc5,0xf8,0x9b,0x51,0x32,0xcf,0x97,0x6c,0xfe,0x4a,0x56,0x3c,
+ 0xc8,0x8f,0x4a,0x70,0x23,0x4f,0xf6,0xf7,0xe6,0x9f,0x09,0xcd,0x8f,0xea,0x20,0x7d,
+ 0x34,0xc0,0xc5,0xc0,0x34,0x06,0x6f,0x8b,0xeb,0x04,0x54,0x3f,0x0e,0xcd,0xe2,0x85,
+ 0xab,0x94,0x3e,0x91,0x6c,0x18,0x6f,0x96,0x5d,0xf2,0x8b,0x10,0xe9,0x90,0x43,0xb0,
+ 0x61,0x52,0xac,0xcf,0x75,0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,
+ 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x09,0x63,
+ 0x42,0xad,0xe5,0xa3,0xf6,0xc9,0x5d,0x08,0xf2,0x78,0x7b,0xeb,0x8a,0xef,0x50,0x00,
+ 0xc8,0xeb,0xe9,0x26,0x94,0xcb,0x84,0x10,0x7e,0x42,0x6b,0x86,0x38,0x57,0xa6,0x02,
+ 0x98,0x5a,0x2c,0x8f,0x44,0x32,0x1b,0x97,0x8c,0x7e,0x4b,0xd8,0xe8,0xe8,0x0f,0x4a,
+ 0xb9,0x31,0x9f,0xf6,0x9f,0x0e,0x67,0x26,0x05,0x2a,0x99,0x14,0x35,0x41,0x47,0x9a,
+ 0xfa,0x12,0x94,0x0b,0xe9,0x27,0x7c,0x71,0x20,0xd7,0x8d,0x3b,0x97,0x19,0x2d,0x15,
+ 0xff,0xa4,0xf3,0x89,0x8d,0x29,0x5f,0xf6,0x3f,0x93,0xaf,0x78,0x61,0xe4,0xe1,0x2e,
+ 0x75,0xc1,0x2c,0xc4,0x76,0x95,0x19,0xf8,0x37,0xdc,0xd8,0x00,0x7a,0x3c,0x0f,0x49,
+ 0x2e,0x88,0x09,0x16,0xb3,0x92,0x33,0xdf,0x77,0x83,0x4f,0xb5,0x9e,0x30,0x8c,0x48,
+ 0x1d,0xd8,0x84,0xfb,0xf1,0xb9,0xa0,0xbe,0x25,0xff,0x4c,0xeb,0xef,0x2b,0xcd,0xfa,
+ 0x0b,0x94,0x66,0x3b,0x28,0x08,0x3f,0x3a,0xda,0x41,0xd0,0x6b,0xab,0x5e,0xbb,0x8a,
+ 0x9f,0xdc,0x98,0x3e,0x59,0x37,0x48,0xbe,0x69,0xde,0x85,0x82,0xf2,0x53,0x8b,0xe4,
+ 0x44,0xe4,0x71,0x91,0x14,0x85,0x0e,0x1e,0x79,0xdd,0x62,0xf5,0xdc,0x25,0x89,0xab,
+ 0x50,0x5b,0xaa,0xae,0xe3,0x64,0x6a,0x23,0x34,0xd7,0x30,0xe2,0x2a,0xc8,0x81,0x0c,
+ 0xec,0xd2,0x31,0xc6,0x1e,0xb6,0xc0,0x57,0xd9,0xe1,0x14,0x06,0x9b,0xf8,0x51,0x69,
+ 0x47,0xf0,0x9c,0xcd,0x69,0xef,0x8e,0x5f,0x62,0xda,0x10,0xf7,0x3c,0x6d,0x0f,0x33,
+ 0xec,0x6f,0xfd,0x94,0x07,0x16,0x41,0x32,0x06,0xa4,0xe1,0x08,0x31,0x87,
+);
+
+/*******************************************************************************
+ * auth info test
+ ******************************************************************************/
+bool test_auth_cfg()
+{
+ auth_cfg_t *auth = auth_cfg_create(), *auth2;
+ certificate_t *c1, *c2;
+ enumerator_t *enumerator;
+ int round = 0;
+ void *value;
+ auth_rule_t type;
+
+ c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, certchunk,
+ BUILD_END);
+ if (!c1)
+ {
+ return FALSE;
+ }
+
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, c1->get_ref(c1));
+ c2 = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!c2)
+ {
+ return FALSE;
+ }
+ if (!c1->equals(c1, c2))
+ {
+ return FALSE;
+ }
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ round++;
+ if (round == 1 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
+ {
+ continue;
+ }
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ auth2 = auth_cfg_create();
+ auth2->add(auth2, AUTH_RULE_CA_CERT, c1->get_ref(c1));
+ auth2->merge(auth2, auth, FALSE);
+
+ round = 0;
+ enumerator = auth2->create_enumerator(auth2);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ round++;
+ if (round == 1 && type == AUTH_RULE_CA_CERT && value == c1)
+ {
+ continue;
+ }
+ if (round == 2 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
+ {
+ continue;
+ }
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+ auth->destroy(auth);
+ auth2->destroy(auth2);
+ c1->destroy(c1);
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_cert.c b/src/libcharon/plugins/unit_tester/tests/test_cert.c
new file mode 100644
index 000000000..3b00421f8
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_cert.c
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+#include <credentials/certificates/x509.h>
+
+/*******************************************************************************
+ * X509 certificate generation and parsing
+ ******************************************************************************/
+bool test_cert_x509()
+{
+ private_key_t *ca_key, *peer_key;
+ public_key_t *public;
+ certificate_t *ca_cert, *peer_cert, *parsed;
+ identification_t *issuer, *subject;
+ u_int32_t serial = htonl(0);
+ chunk_t encoding;
+
+ issuer = identification_create_from_string("CN=CA, OU=Test, O=strongSwan");
+ subject = identification_create_from_string("CN=Peer, OU=Test, O=strongSwan");
+
+ ca_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_KEY_SIZE, 1024, BUILD_END);
+ peer_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_KEY_SIZE, 1024, BUILD_END);
+ if (!ca_key)
+ {
+ return FALSE;
+ }
+ ca_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_SIGNING_KEY, ca_key,
+ BUILD_SUBJECT, issuer,
+ BUILD_SERIAL, chunk_from_thing(serial),
+ BUILD_X509_FLAG, X509_CA,
+ BUILD_END);
+ if (!ca_cert)
+ {
+ return FALSE;
+ }
+
+ encoding = ca_cert->get_encoding(ca_cert);
+ parsed = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ chunk_free(&encoding);
+ if (!parsed)
+ {
+ return FALSE;
+ }
+ if (!parsed->issued_by(parsed, ca_cert))
+ {
+ return FALSE;
+ }
+ parsed->destroy(parsed);
+
+ serial = htonl(ntohl(serial) + 1);
+ public = peer_key->get_public_key(peer_key);
+ peer_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_SIGNING_KEY, ca_key,
+ BUILD_SIGNING_CERT, ca_cert,
+ BUILD_PUBLIC_KEY, public,
+ BUILD_SUBJECT, subject,
+ BUILD_SERIAL, chunk_from_thing(serial),
+ BUILD_END);
+ public->destroy(public);
+ if (!peer_cert)
+ {
+ return FALSE;
+ }
+
+ encoding = peer_cert->get_encoding(peer_cert);
+ parsed = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ chunk_free(&encoding);
+ if (!parsed)
+ {
+ return FALSE;
+ }
+ if (!parsed->issued_by(parsed, ca_cert))
+ {
+ return FALSE;
+ }
+ parsed->destroy(parsed);
+
+ ca_cert->destroy(ca_cert);
+ ca_key->destroy(ca_key);
+ peer_cert->destroy(peer_cert);
+ peer_key->destroy(peer_key);
+ issuer->destroy(issuer);
+ subject->destroy(subject);
+ return TRUE;
+}
+
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_chunk.c b/src/libcharon/plugins/unit_tester/tests/test_chunk.c
new file mode 100644
index 000000000..2e0905b2c
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_chunk.c
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+
+/*******************************************************************************
+ * Base64 encoding/decoding test
+ ******************************************************************************/
+bool test_chunk_base64()
+{
+ /* test vectors from RFC4648:
+ *
+ * BASE64("") = ""
+ * BASE64("f") = "Zg=="
+ * BASE64("fo") = "Zm8="
+ * BASE64("foo") = "Zm9v"
+ * BASE64("foob") = "Zm9vYg=="
+ * BASE64("fooba") = "Zm9vYmE="
+ * BASE64("foobar") = "Zm9vYmFy"
+ */
+
+ typedef struct {
+ char *in;
+ char *out;
+ } testdata_t;
+
+ testdata_t test[] = {
+ {"", ""},
+ {"f", "Zg=="},
+ {"fo", "Zm8="},
+ {"foo", "Zm9v"},
+ {"foob", "Zm9vYg=="},
+ {"fooba", "Zm9vYmE="},
+ {"foobar", "Zm9vYmFy"},
+ };
+ int i;
+
+ for (i = 0; i < countof(test); i++)
+ {
+ chunk_t out;
+
+ out = chunk_to_base64(chunk_create(test[i].in, strlen(test[i].in)), NULL);
+
+ if (!streq(out.ptr, test[i].out))
+ {
+ DBG1(DBG_CFG, "base64 conversion error - should %s, is %s",
+ test[i].out, out.ptr);
+ return FALSE;
+ }
+ free(out.ptr);
+ }
+
+ for (i = 0; i < countof(test); i++)
+ {
+ chunk_t out;
+
+ out = chunk_from_base64(chunk_create(test[i].out, strlen(test[i].out)), NULL);
+
+ if (!strneq(out.ptr, test[i].in, out.len))
+ {
+ DBG1(DBG_CFG, "base64 conversion error - should %s, is %#B",
+ test[i].in, &out);
+ return FALSE;
+ }
+ free(out.ptr);
+ }
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_curl.c b/src/libcharon/plugins/unit_tester/tests/test_curl.c
new file mode 100644
index 000000000..21656a94e
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_curl.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <daemon.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+/*******************************************************************************
+ * curl get test
+ ******************************************************************************/
+
+bool test_curl_get()
+{
+ chunk_t chunk;
+
+ if (lib->fetcher->fetch(lib->fetcher, "http://www.strongswan.org",
+ &chunk, FETCH_END) != SUCCESS)
+ {
+ return FALSE;
+ }
+ free(chunk.ptr);
+
+ if (lib->fetcher->fetch(lib->fetcher, "http://www.google.com",
+ &chunk, FETCH_END) != SUCCESS)
+ {
+ return FALSE;
+ }
+ free(chunk.ptr);
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_enumerator.c b/src/libcharon/plugins/unit_tester/tests/test_enumerator.c
new file mode 100644
index 000000000..edbf0f5bb
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_enumerator.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/linked_list.h>
+
+
+/*******************************************************************************
+ * linked list remove test
+ ******************************************************************************/
+bool test_list_remove()
+{
+ void *a = (void*)1, *b = (void*)2;
+ linked_list_t *list;
+
+ list = linked_list_create();
+ list->insert_last(list, a);
+ if (list->remove(list, a, NULL) != 1)
+ {
+ return FALSE;
+ }
+ list->insert_last(list, a);
+ list->insert_first(list, a);
+ list->insert_last(list, a);
+ list->insert_last(list, b);
+ if (list->remove(list, a, NULL) != 3)
+ {
+ return FALSE;
+ }
+ if (list->remove(list, a, NULL) != 0)
+ {
+ return FALSE;
+ }
+ if (list->get_count(list) != 1)
+ {
+ return FALSE;
+ }
+ if (list->remove(list, b, NULL) != 1)
+ {
+ return FALSE;
+ }
+ if (list->remove(list, b, NULL) != 0)
+ {
+ return FALSE;
+ }
+ list->destroy(list);
+ return TRUE;
+}
+
+/*******************************************************************************
+ * Simple insert first/last and enumerate test
+ ******************************************************************************/
+bool test_enumerate()
+{
+ int round, x;
+ void *a = (void*)4, *b = (void*)3, *c = (void*)2, *d = (void*)5, *e = (void*)1;
+ linked_list_t *list;
+ enumerator_t *enumerator;
+
+ list = linked_list_create();
+
+ list->insert_last(list, a);
+ list->insert_first(list, b);
+ list->insert_first(list, c);
+ list->insert_last(list, d);
+ list->insert_first(list, e);
+
+ round = 1;
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &x))
+ {
+ if (round != x)
+ {
+ return FALSE;
+ }
+ round++;
+ }
+ enumerator->destroy(enumerator);
+
+ list->destroy(list);
+ return TRUE;
+}
+
+/*******************************************************************************
+ * nested enumerator test
+ ******************************************************************************/
+
+static bool bad_data;
+
+static enumerator_t* create_inner(linked_list_t *outer, void *data)
+{
+ if (data != (void*)101)
+ {
+ bad_data = TRUE;
+ }
+ return outer->create_enumerator(outer);
+}
+
+
+static void destroy_data(void *data)
+{
+ if (data != (void*)101)
+ {
+ bad_data = TRUE;
+ }
+}
+
+bool test_enumerate_nested()
+{
+ int round, x;
+ void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5;
+ linked_list_t *list, *l1, *l2, *l3;
+ enumerator_t *enumerator;
+
+ bad_data = FALSE;
+ list = linked_list_create();
+ l1 = linked_list_create();
+ l2 = linked_list_create();
+ l3 = linked_list_create();
+ list->insert_last(list, l1);
+ list->insert_last(list, l2);
+ list->insert_last(list, l3);
+
+ l1->insert_last(l1, a);
+ l1->insert_last(l1, b);
+ l3->insert_last(l3, c);
+ l3->insert_last(l3, d);
+ l3->insert_last(l3, e);
+
+ round = 1;
+ enumerator = enumerator_create_nested(list->create_enumerator(list),
+ (void*)create_inner, (void*)101, destroy_data);
+ while (enumerator->enumerate(enumerator, &x))
+ {
+ if (round != x)
+ {
+ return FALSE;
+ }
+ round++;
+ }
+ enumerator->destroy(enumerator);
+
+ list->destroy(list);
+ l1->destroy(l1);
+ l2->destroy(l2);
+ l3->destroy(l3);
+ return !bad_data;
+}
+
+
+/*******************************************************************************
+ * filtered enumerator test
+ ******************************************************************************/
+static bool filter(void *data, int *v, int *vo, int *w, int *wo,
+ int *x, int *xo, int *y, int *yo, int *z, int *zo)
+{
+ int val = *v;
+
+ *vo = val++;
+ *wo = val++;
+ *xo = val++;
+ *yo = val++;
+ *zo = val++;
+ if (data != (void*)101)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool test_enumerate_filtered()
+{
+ int round, v, w, x, y, z;
+ void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5;
+ linked_list_t *list;
+ enumerator_t *enumerator;
+
+ bad_data = FALSE;
+ list = linked_list_create();
+
+ list->insert_last(list, a);
+ list->insert_last(list, b);
+ list->insert_last(list, c);
+ list->insert_last(list, d);
+ list->insert_last(list, e);
+
+ round = 1;
+ enumerator = enumerator_create_filter(list->create_enumerator(list),
+ (void*)filter, (void*)101, destroy_data);
+ while (enumerator->enumerate(enumerator, &v, &w, &x, &y, &z))
+ {
+ if (v != round || w != round + 1 || x != round + 2 ||
+ y != round + 3 || z != round + 4)
+ {
+ return FALSE;
+ }
+ round++;
+ }
+ enumerator->destroy(enumerator);
+
+ list->destroy(list);
+ return !bad_data;
+}
+
+/*******************************************************************************
+ * token parser test
+ ******************************************************************************/
+
+bool test_enumerate_token()
+{
+ enumerator_t *enumerator;
+ char *token;
+ int i, num;
+ struct {
+ char *string;
+ char *sep;
+ char *trim;
+ } tests1[] = {
+ {"abc, cde, efg", ",", " "},
+ {" abc 1:2 cde;3 4efg5. ", ":;.,", " 12345"},
+ {"abc.cde,efg", ",.", ""},
+ {" abc cde efg ", " ", " "},
+ {"a'abc' c 'cde' cefg", " ", " abcd"},
+ {"'abc' abc 'cde'd 'efg'", " ", " abcd"},
+ }, tests2[] = {
+ {"a, b, c", ",", " "},
+ {"a,b,c", ",", " "},
+ {" a 1:2 b;3 4c5. ", ":;.,", " 12345"},
+ {"a.b,c", ",.", ""},
+ {" a b c ", " ", " "},
+ };
+
+ for (num = 0; num < countof(tests1); num++)
+ {
+ i = 0;
+ enumerator = enumerator_create_token(tests1[num].string,
+ tests1[num].sep, tests1[num].trim);
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ switch (i)
+ {
+ case 0:
+ if (!streq(token, "abc")) return FALSE;
+ break;
+ case 1:
+ if (!streq(token, "cde")) return FALSE;
+ break;
+ case 2:
+ if (!streq(token, "efg")) return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+ i++;
+ }
+ if (i != 3)
+ {
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ for (num = 0; num < countof(tests2); num++)
+ {
+ i = 0;
+ enumerator = enumerator_create_token(tests2[num].string,
+ tests2[num].sep, tests2[num].trim);
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ switch (i)
+ {
+ case 0:
+ if (!streq(token, "a")) return FALSE;
+ break;
+ case 1:
+ if (!streq(token, "b")) return FALSE;
+ break;
+ case 2:
+ if (!streq(token, "c")) return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+ i++;
+ }
+ if (i != 3)
+ {
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_id.c b/src/libcharon/plugins/unit_tester/tests/test_id.c
new file mode 100644
index 000000000..868a2ca8b
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_id.c
@@ -0,0 +1,249 @@
+/*
+ * 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 <daemon.h>
+
+/*******************************************************************************
+ * identification part enumeration test
+ ******************************************************************************/
+bool test_id_parts()
+{
+ identification_t *id;
+ enumerator_t *enumerator;
+ id_part_t part;
+ chunk_t data;
+ int i = 0;
+
+ id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
+
+ enumerator = id->create_part_enumerator(id);
+ while (enumerator->enumerate(enumerator, &part, &data))
+ {
+ switch (i++)
+ {
+ case 0:
+ if (part != ID_PART_RDN_C ||
+ !chunk_equals(data, chunk_create("CH", 2)))
+ {
+ return FALSE;
+ }
+ break;
+ case 1:
+ if (part != ID_PART_RDN_O ||
+ !chunk_equals(data, chunk_create("strongSwan", 10)))
+ {
+ return FALSE;
+ }
+ break;
+ case 2:
+ if (part != ID_PART_RDN_CN ||
+ !chunk_equals(data, chunk_create("tester", 6)))
+ {
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ if (i < 3)
+ {
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+ id->destroy(id);
+ return TRUE;
+}
+
+/*******************************************************************************
+ * identification contains_wildcards() test
+ ******************************************************************************/
+
+static bool test_id_wildcards_has(char *string)
+{
+ identification_t *id;
+ bool contains;
+
+ id = identification_create_from_string(string);
+ contains = id->contains_wildcards(id);
+ id->destroy(id);
+ return contains;
+}
+
+bool test_id_wildcards()
+{
+ if (!test_id_wildcards_has("C=*, O=strongSwan, CN=gw"))
+ {
+ return FALSE;
+ }
+ if (!test_id_wildcards_has("C=CH, O=strongSwan, CN=*"))
+ {
+ return FALSE;
+ }
+ if (test_id_wildcards_has("C=**, O=a*, CN=*a"))
+ {
+ return FALSE;
+ }
+ if (!test_id_wildcards_has("*@strongswan.org"))
+ {
+ return FALSE;
+ }
+ if (!test_id_wildcards_has("*.strongswan.org"))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*******************************************************************************
+ * identification equals test
+ ******************************************************************************/
+
+static bool test_id_equals_one(identification_t *a, char *b_str)
+{
+ identification_t *b;
+ bool equals;
+
+ b = identification_create_from_string(b_str);
+ equals = a->equals(a, b);
+ b->destroy(b);
+ return equals;
+}
+
+bool test_id_equals()
+{
+ identification_t *a;
+ chunk_t encoding, fuzzed;
+ int i;
+
+ a = identification_create_from_string(
+ "C=CH, E=martin@strongswan.org, CN=martin");
+
+ if (!test_id_equals_one(a, "C=CH, E=martin@strongswan.org, CN=martin"))
+ {
+ return FALSE;
+ }
+ if (!test_id_equals_one(a, "C=ch, E=martin@STRONGSWAN.ORG, CN=Martin"))
+ {
+ return FALSE;
+ }
+ if (test_id_equals_one(a, "C=CN, E=martin@strongswan.org, CN=martin"))
+ {
+ return FALSE;
+ }
+ if (test_id_equals_one(a, "E=martin@strongswan.org, C=CH, CN=martin"))
+ {
+ return FALSE;
+ }
+ if (test_id_equals_one(a, "E=martin@strongswan.org, C=CH, CN=martin"))
+ {
+ return FALSE;
+ }
+ encoding = chunk_clone(a->get_encoding(a));
+ a->destroy(a);
+
+ /* simple fuzzing, increment each byte of encoding */
+ for (i = 0; i < encoding.len; i++)
+ {
+ if (i == 11 || i == 30 || i == 62)
+ { /* skip ASN.1 type fields, as equals() handles them graceful */
+ continue;
+ }
+ fuzzed = chunk_clone(encoding);
+ fuzzed.ptr[i]++;
+ a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
+ if (test_id_equals_one(a, "C=CH, E=martin@strongswan.org, CN=martin"))
+ {
+ return FALSE;
+ }
+ a->destroy(a);
+ free(fuzzed.ptr);
+ }
+
+ /* and decrement each byte of encoding */
+ for (i = 0; i < encoding.len; i++)
+ {
+ if (i == 11 || i == 30 || i == 62)
+ {
+ continue;
+ }
+ fuzzed = chunk_clone(encoding);
+ fuzzed.ptr[i]--;
+ a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
+ if (test_id_equals_one(a, "C=CH, E=martin@strongswan.org, CN=martin"))
+ {
+ return FALSE;
+ }
+ a->destroy(a);
+ free(fuzzed.ptr);
+ }
+ free(encoding.ptr);
+ return TRUE;
+}
+
+/*******************************************************************************
+ * identification matches test
+ ******************************************************************************/
+
+static id_match_t test_id_matches_one(identification_t *a, char *b_str)
+{
+ identification_t *b;
+ id_match_t match;
+
+ b = identification_create_from_string(b_str);
+ match = a->matches(a, b);
+ b->destroy(b);
+ return match;
+}
+
+bool test_id_matches()
+{
+ identification_t *a;
+
+ a = identification_create_from_string(
+ "C=CH, E=martin@strongswan.org, CN=martin");
+
+ if (test_id_matches_one(a, "C=CH, E=martin@strongswan.org, CN=martin")
+ != ID_MATCH_PERFECT)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=CH, E=*, CN=martin") != ID_MATCH_ONE_WILDCARD)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=CH, E=*, CN=*") != ID_MATCH_ONE_WILDCARD - 1)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=*, E=*, CN=*") != ID_MATCH_ONE_WILDCARD - 2)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=*, E=*, CN=*, O=BADInc") != ID_MATCH_NONE)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=*, E=*") != ID_MATCH_NONE)
+ {
+ return FALSE;
+ }
+ if (test_id_matches_one(a, "C=*, E=a@b.c, CN=*") != ID_MATCH_NONE)
+ {
+ return FALSE;
+ }
+ a->destroy(a);
+ return TRUE;
+}
diff --git a/src/libcharon/plugins/unit_tester/tests/test_med_db.c b/src/libcharon/plugins/unit_tester/tests/test_med_db.c
new file mode 100644
index 000000000..7fd78b0bc
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_med_db.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+#include <utils/enumerator.h>
+
+#include <unistd.h>
+
+/*******************************************************************************
+ * fetch public key from mediation database
+ ******************************************************************************/
+
+bool test_med_db()
+{
+ chunk_t found, keyid = chunk_from_chars(
+ 0xed,0x90,0xe6,0x4f,0xec,0xa2,0x1f,0x4b,
+ 0x68,0x97,0x99,0x24,0x22,0xe0,0xde,0x21,
+ 0xb9,0xd6,0x26,0x29
+ );
+ identification_t *id;
+ enumerator_t *enumerator;
+ public_key_t *public;
+ auth_cfg_t *auth;
+ bool good = FALSE;
+
+ id = identification_create_from_encoding(ID_KEY_ID, keyid);
+ enumerator = charon->credentials->create_public_enumerator(
+ charon->credentials, KEY_ANY, id, NULL);
+ while (enumerator->enumerate(enumerator, &public, &auth))
+ {
+ good = public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &found);
+ if (good)
+ {
+ good = chunk_equals(id->get_encoding(id), found);
+ }
+ }
+ enumerator->destroy(enumerator);
+ id->destroy(id);
+ return good;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_mutex.c b/src/libcharon/plugins/unit_tester/tests/test_mutex.c
new file mode 100644
index 000000000..77085cb2f
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_mutex.c
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <threading/mutex.h>
+
+#include <unistd.h>
+#include <sched.h>
+#include <pthread.h>
+
+
+static mutex_t *mutex;
+
+static int locked = 0;
+
+static bool failed = FALSE;
+
+static pthread_barrier_t barrier;
+
+static void* run(void* null)
+{
+ int i;
+
+ /* wait for all threads before getting in action */
+ pthread_barrier_wait(&barrier);
+
+ for (i = 0; i < 100; i++)
+ {
+ mutex->lock(mutex);
+ mutex->lock(mutex);
+ mutex->lock(mutex);
+ locked++;
+ sched_yield();
+ if (locked > 1)
+ {
+ failed = TRUE;
+ }
+ locked--;
+ mutex->unlock(mutex);
+ mutex->unlock(mutex);
+ mutex->unlock(mutex);
+ }
+ return NULL;
+}
+
+#define THREADS 20
+
+/*******************************************************************************
+ * mutex test
+ ******************************************************************************/
+bool test_mutex()
+{
+ int i;
+ pthread_t threads[THREADS];
+
+ mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+
+ for (i = 0; i < 10; i++)
+ {
+ mutex->lock(mutex);
+ mutex->unlock(mutex);
+ }
+ for (i = 0; i < 10; i++)
+ {
+ mutex->lock(mutex);
+ }
+ for (i = 0; i < 10; i++)
+ {
+ mutex->unlock(mutex);
+ }
+
+ pthread_barrier_init(&barrier, NULL, THREADS);
+
+ for (i = 0; i < THREADS; i++)
+ {
+ pthread_create(&threads[i], NULL, run, NULL);
+ }
+ for (i = 0; i < THREADS; i++)
+ {
+ pthread_join(threads[i], NULL);
+ }
+ pthread_barrier_destroy(&barrier);
+
+ mutex->destroy(mutex);
+
+ return !failed;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_mysql.c b/src/libcharon/plugins/unit_tester/tests/test_mysql.c
new file mode 100644
index 000000000..252441ef8
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_mysql.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+#include <utils/enumerator.h>
+
+/*******************************************************************************
+ * mysql simple test
+ ******************************************************************************/
+bool test_mysql()
+{
+ database_t *db;
+ char *txt = "I'm a superduper test";
+ chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08);
+ int row;
+ chunk_t qdata;
+ char *qtxt;
+ bool good = FALSE;
+ enumerator_t *enumerator;
+
+ db = lib->db->create(lib->db, "mysql://testuser:testpass@localhost/test");
+ if (!db)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "CREATE TABLE test ("
+ "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, "
+ "txt TEXT, data BLOB)") < 0)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)",
+ DB_TEXT, txt, DB_BLOB, data) < 0)
+ {
+ return FALSE;
+ }
+ if (row != 1)
+ {
+ return FALSE;
+ }
+ enumerator = db->query(db, "SELECT txt, data FROM test WHERE id = ?",
+ DB_INT, row,
+ DB_TEXT, DB_BLOB);
+ if (!enumerator)
+ {
+ return FALSE;
+ }
+ while (enumerator->enumerate(enumerator, &qtxt, &qdata))
+ {
+ if (good)
+ { /* only one row */
+ good = FALSE;
+ break;
+ }
+ if (streq(qtxt, txt) && chunk_equals(data, qdata))
+ {
+ good = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!good)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "DELETE FROM test WHERE id = ?", DB_INT, row) != 1)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "DROP TABLE test") < 0)
+ {
+ return FALSE;
+ }
+ db->destroy(db);
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_pool.c b/src/libcharon/plugins/unit_tester/tests/test_pool.c
new file mode 100644
index 000000000..a68246fff
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_pool.c
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include <time.h>
+
+#include <library.h>
+#include <threading/thread.h>
+#include <hydra.h>
+
+#define ALLOCS 1000
+#define THREADS 20
+
+static void* testing(void *thread)
+{
+ int i;
+ host_t *addr[ALLOCS];
+ identification_t *id[ALLOCS];
+
+ /* prepare identities */
+ for (i = 0; i < ALLOCS; i++)
+ {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "%d-%d@strongswan.org", (uintptr_t)thread, i);
+ id[i] = identification_create_from_string(buf);
+ }
+
+ /* allocate addresses */
+ for (i = 0; i < ALLOCS; i++)
+ {
+ addr[i] = hydra->attributes->acquire_address(hydra->attributes,
+ "test", id[i], NULL);
+ if (!addr[i])
+ {
+ return (void*)FALSE;
+ }
+ }
+
+ /* release addresses */
+ for (i = 0; i < ALLOCS; i++)
+ {
+ hydra->attributes->release_address(hydra->attributes,
+ "test", addr[i], id[i]);
+ }
+
+ /* cleanup */
+ for (i = 0; i < ALLOCS; i++)
+ {
+ addr[i]->destroy(addr[i]);
+ id[i]->destroy(id[i]);
+ }
+ return (void*)TRUE;
+}
+
+
+/*******************************************************************************
+ * SQL pool performance test
+ ******************************************************************************/
+bool test_pool()
+{
+ thread_t *threads[THREADS];
+ uintptr_t i;
+
+ for (i = 0; i < THREADS; i++)
+ {
+ if (!(threads[i] = thread_create((thread_main_t)testing, (void*)i)))
+ {
+ return FALSE;
+ }
+ }
+ for (i = 0; i < THREADS; i++)
+ {
+ bool *res = threads[i]->join(threads[i]);
+ if (!res)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_rsa_gen.c b/src/libcharon/plugins/unit_tester/tests/test_rsa_gen.c
new file mode 100644
index 000000000..59da15644
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_rsa_gen.c
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+
+/*******************************************************************************
+ * RSA key generation and signature
+ ******************************************************************************/
+bool test_rsa_gen()
+{
+ chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08);
+ chunk_t sig, crypt, plain;
+ private_key_t *private;
+ public_key_t *public;
+ u_int key_size;
+
+ for (key_size = 512; key_size <= 2048; key_size *= 2)
+ {
+ private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_KEY_SIZE, key_size, BUILD_END);
+ if (!private)
+ {
+ DBG1(DBG_CFG, "generating %d bit RSA key failed");
+ return FALSE;
+ }
+ public = private->get_public_key(private);
+ if (!public)
+ {
+ DBG1(DBG_CFG, "generating public from private key failed");
+ return FALSE;
+ }
+ if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_SHA1, data, &sig))
+ {
+ DBG1(DBG_CFG, "creating RSA signature failed");
+ return FALSE;
+ }
+ if (!public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig))
+ {
+ DBG1(DBG_CFG, "verifying RSA signature failed");
+ return FALSE;
+ }
+ sig.ptr[sig.len-1]++;
+ if (public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig))
+ {
+ DBG1(DBG_CFG, "verifying faked RSA signature succeeded!");
+ return FALSE;
+ }
+ free(sig.ptr);
+ if (!public->encrypt(public, data, &crypt))
+ {
+ DBG1(DBG_CFG, "encrypting data with RSA failed");
+ return FALSE;
+ }
+ if (!private->decrypt(private, crypt, &plain))
+ {
+ DBG1(DBG_CFG, "decrypting data with RSA failed");
+ return FALSE;
+ }
+ if (!chunk_equals(data, plain))
+ {
+ DBG1(DBG_CFG, "decrpyted data invalid, expected %B, got %B", &
+ data, &plain);
+ return FALSE;
+ }
+ chunk_clear(&crypt);
+ chunk_clear(&plain);
+ public->destroy(public);
+ private->destroy(private);
+ }
+ return TRUE;
+}
+
+bool test_rsa_load_any()
+{
+ chunk_t chunk = chunk_from_chars(
+ 0x30,0x82,0x01,0x20,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
+ 0x01,0x05,0x00,0x03,0x82,0x01,0x0d,0x00,0x30,0x82,0x01,0x08,0x02,0x82,0x01,0x01,
+ 0x00,0xc6,0x68,0x99,0x1d,0xc8,0x06,0xdb,0xcf,0x1c,0x66,0xbb,0x91,0xc3,0xd4,0x10,
+ 0xb2,0x08,0xa9,0xc5,0x71,0x39,0x1c,0xbe,0x5b,0x1d,0xce,0xfd,0x1b,0xfa,0xec,0x04,
+ 0x89,0x9f,0x79,0xc8,0x46,0x00,0xd2,0x71,0xfb,0x22,0x16,0x52,0x2f,0xda,0xbf,0x0f,
+ 0xe7,0x16,0xb1,0xd7,0x6a,0xa5,0xa5,0xfc,0xee,0xff,0x84,0x4c,0x81,0x3f,0xab,0x84,
+ 0x0e,0xed,0x4a,0x26,0x59,0xd0,0x9b,0xb5,0xe1,0xec,0x61,0xc4,0xd3,0x15,0x4c,0x29,
+ 0x51,0xa0,0xde,0x33,0x07,0x58,0x6c,0x36,0x1b,0x18,0x61,0xd9,0x56,0x18,0x39,0x54,
+ 0x8b,0xd2,0xea,0x4e,0x87,0x28,0x58,0xb9,0x88,0x3d,0x30,0xbc,0xfc,0x6d,0xad,0xab,
+ 0x43,0x26,0x09,0x48,0x4e,0x6e,0x8a,0x8b,0x88,0xb3,0xf0,0x29,0x25,0x79,0xb6,0xb6,
+ 0x71,0x3c,0x93,0x59,0xd2,0x36,0x94,0xd5,0xfc,0xf3,0x62,0x2b,0x69,0xa3,0x7a,0x47,
+ 0x4e,0x53,0xa2,0x35,0x1b,0x26,0x89,0xaa,0x09,0xfd,0x56,0xd7,0x75,0x2a,0xd4,0x91,
+ 0xc0,0xf2,0x78,0xd7,0x05,0xca,0x12,0x1d,0xd9,0xd4,0x81,0x23,0xb2,0x3c,0x38,0xd9,
+ 0xb4,0xdc,0x21,0xe0,0xe5,0x2d,0xd4,0xbe,0x61,0x39,0x8a,0x46,0x90,0x46,0x73,0x31,
+ 0xba,0x48,0xbb,0x51,0xbb,0x91,0xd5,0x62,0xad,0xd1,0x53,0x5b,0x85,0xc9,0x1d,0xa7,
+ 0xf6,0xa0,0xe1,0x0e,0x6c,0x22,0x5d,0x29,0x9a,0xe7,0x0f,0xe8,0x0a,0x50,0xa7,0x19,
+ 0x11,0xc2,0x8b,0xe0,0x8a,0xfd,0x2b,0x94,0x31,0x7a,0x78,0x9c,0x9b,0x75,0x63,0x49,
+ 0xa9,0xe5,0x58,0xe6,0x3a,0x99,0xcb,0x2b,0xdd,0x0e,0xdc,0x7d,0x1b,0x98,0x80,0xc3,
+ 0x9f,0x02,0x01,0x23);
+ public_key_t *public;
+
+ public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ BUILD_BLOB_ASN1_DER, chunk,
+ BUILD_END);
+ if (!public || public->get_keysize(public) != 256)
+ {
+ return FALSE;
+ }
+ public->destroy(public);
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/tests/test_sqlite.c b/src/libcharon/plugins/unit_tester/tests/test_sqlite.c
new file mode 100644
index 000000000..dd8d1955e
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_sqlite.c
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include <library.h>
+#include <daemon.h>
+#include <utils/enumerator.h>
+
+#include <unistd.h>
+
+
+#define DBFILE "/tmp/strongswan-test.db"
+
+/*******************************************************************************
+ * sqlite simple test
+ ******************************************************************************/
+bool test_sqlite()
+{
+ database_t *db;
+ char *txt = "I'm a superduper test";
+ chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08);
+ int row;
+ chunk_t qdata;
+ char *qtxt;
+ bool good = FALSE;
+ enumerator_t *enumerator;
+
+ db = lib->db->create(lib->db, "sqlite://" DBFILE);
+ if (!db)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "CREATE TABLE test (txt TEXT, data BLOB)") < 0)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)",
+ DB_TEXT, txt, DB_BLOB, data) < 0)
+ {
+ return FALSE;
+ }
+ if (row != 1)
+ {
+ return FALSE;
+ }
+ enumerator = db->query(db, "SELECT txt, data FROM test WHERE oid = ?",
+ DB_INT, row,
+ DB_TEXT, DB_BLOB);
+ if (!enumerator)
+ {
+ return FALSE;
+ }
+ while (enumerator->enumerate(enumerator, &qtxt, &qdata))
+ {
+ if (good)
+ { /* only one row */
+ good = FALSE;
+ break;
+ }
+ if (streq(qtxt, txt) && chunk_equals(data, qdata))
+ {
+ good = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!good)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "DELETE FROM test WHERE oid = ?", DB_INT, row) != 1)
+ {
+ return FALSE;
+ }
+ if (db->execute(db, NULL, "DROP TABLE test") < 0)
+ {
+ return FALSE;
+ }
+ db->destroy(db);
+ unlink(DBFILE);
+ return TRUE;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/unit_tester.c b/src/libcharon/plugins/unit_tester/unit_tester.c
new file mode 100644
index 000000000..5f6f94e03
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/unit_tester.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "unit_tester.h"
+
+#include <daemon.h>
+
+typedef struct private_unit_tester_t private_unit_tester_t;
+typedef struct unit_test_t unit_test_t;
+typedef enum test_status_t test_status_t;
+
+/**
+ * private data of unit_tester
+ */
+struct private_unit_tester_t {
+
+ /**
+ * public functions
+ */
+ unit_tester_t public;
+};
+
+struct unit_test_t {
+
+ /**
+ * name of the test
+ */
+ char *name;
+
+ /**
+ * test function
+ */
+ bool (*test)(void);
+
+ /**
+ * run the test?
+ */
+ bool enabled;
+};
+
+#undef DEFINE_TEST
+#define DEFINE_TEST(name, function, enabled) bool function();
+#include <plugins/unit_tester/tests.h>
+#undef DEFINE_TEST
+#define DEFINE_TEST(name, function, enabled) {name, function, enabled},
+static unit_test_t tests[] = {
+#include <plugins/unit_tester/tests.h>
+};
+
+static void run_tests(private_unit_tester_t *this)
+{
+ int i, run = 0, failed = 0, success = 0, skipped = 0;
+
+ DBG1(DBG_CFG, "running unit tests, %d tests registered",
+ sizeof(tests)/sizeof(unit_test_t));
+
+ for (i = 0; i < sizeof(tests)/sizeof(unit_test_t); i++)
+ {
+ if (tests[i].enabled)
+ {
+ run++;
+ if (tests[i].test())
+ {
+ DBG1(DBG_CFG, "test '%s' successful", tests[i].name);
+ success++;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "test '%s' failed", tests[i].name);
+ failed++;
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "test '%s' disabled", tests[i].name);
+ skipped++;
+ }
+ }
+ DBG1(DBG_CFG, "%d/%d tests successful (%d failed, %d disabled)",
+ success, run, failed, skipped);
+}
+
+/**
+ * Implementation of 2007_t.destroy
+ */
+static void destroy(private_unit_tester_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *unit_tester_plugin_create()
+{
+ private_unit_tester_t *this = malloc_thing(private_unit_tester_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ run_tests(this);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/unit_tester/unit_tester.h b/src/libcharon/plugins/unit_tester/unit_tester.h
new file mode 100644
index 000000000..08784f6f4
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/unit_tester.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unit_tester unit_tester
+ * @{ @ingroup cplugins
+ */
+
+#ifndef UNIT_TESTER_H_
+#define UNIT_TESTER_H_
+
+#include <plugins/plugin.h>
+
+typedef struct unit_tester_t unit_tester_t;
+
+/**
+ * Unit testing plugin.
+ *
+ * The unit testing plugin runs tests on plugin initialization. Tests are
+ * defined in tests.h using the DEFINE_TEST macro. Implementation of the
+ * tests is done in the tests folder. Each test has uses a function which
+ * returns TRUE for success or FALSE for failure.
+ */
+struct unit_tester_t {
+
+ /**
+ * Implements the plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** UNIT_TESTER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
new file mode 100644
index 000000000..312c8d7e8
--- /dev/null
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-updown.la
+else
+plugin_LTLIBRARIES = libstrongswan-updown.la
+endif
+
+libstrongswan_updown_la_SOURCES = \
+ updown_plugin.h updown_plugin.c \
+ updown_listener.h updown_listener.c
+
+libstrongswan_updown_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
new file mode 100644
index 000000000..d3c509a32
--- /dev/null
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -0,0 +1,589 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/updown
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_updown_la_LIBADD =
+am_libstrongswan_updown_la_OBJECTS = updown_plugin.lo \
+ updown_listener.lo
+libstrongswan_updown_la_OBJECTS = \
+ $(am_libstrongswan_updown_la_OBJECTS)
+libstrongswan_updown_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_updown_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_updown_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_updown_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_updown_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_updown_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-updown.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-updown.la
+libstrongswan_updown_la_SOURCES = \
+ updown_plugin.h updown_plugin.c \
+ updown_listener.h updown_listener.c
+
+libstrongswan_updown_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/updown/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/updown/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-updown.la: $(libstrongswan_updown_la_OBJECTS) $(libstrongswan_updown_la_DEPENDENCIES)
+ $(libstrongswan_updown_la_LINK) $(am_libstrongswan_updown_la_rpath) $(libstrongswan_updown_la_OBJECTS) $(libstrongswan_updown_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
new file mode 100644
index 000000000..5a6746f92
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -0,0 +1,294 @@
+/*
+ * 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 <stdio.h>
+
+#include "updown_listener.h"
+
+#include <daemon.h>
+#include <config/child_cfg.h>
+
+typedef struct private_updown_listener_t private_updown_listener_t;
+
+/**
+ * Private data of an updown_listener_t object.
+ */
+struct private_updown_listener_t {
+
+ /**
+ * Public updown_listener_t interface.
+ */
+ updown_listener_t public;
+
+ /**
+ * List of cached interface names
+ */
+ linked_list_t *iface_cache;
+};
+
+typedef struct cache_entry_t cache_entry_t;
+
+/**
+ * Cache line in the interface name cache.
+ */
+struct cache_entry_t {
+ /** requid of the CHILD_SA */
+ u_int32_t reqid;
+ /** cached interface name */
+ char *iface;
+};
+
+/**
+ * Insert an interface name to the cache
+ */
+static void cache_iface(private_updown_listener_t *this, u_int32_t reqid,
+ char *iface)
+{
+ cache_entry_t *entry = malloc_thing(cache_entry_t);
+
+ entry->reqid = reqid;
+ entry->iface = strdup(iface);
+
+ this->iface_cache->insert_first(this->iface_cache, entry);
+}
+
+/**
+ * Remove a cached interface name and return it.
+ */
+static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
+{
+ enumerator_t *enumerator;
+ cache_entry_t *entry;
+ char *iface = NULL;
+
+ enumerator = this->iface_cache->create_enumerator(this->iface_cache);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->reqid == reqid)
+ {
+ this->iface_cache->remove_at(this->iface_cache, enumerator);
+ iface = entry->iface;
+ free(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return iface;
+}
+
+METHOD(listener_t, child_updown, bool,
+ private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ bool up)
+{
+ traffic_selector_t *my_ts, *other_ts;
+ enumerator_t *enumerator;
+ child_cfg_t *config;
+ host_t *vip, *me, *other;
+ char *script;
+
+ config = child_sa->get_config(child_sa);
+ vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
+ script = config->get_updown(config);
+ me = ike_sa->get_my_host(ike_sa);
+ other = ike_sa->get_other_host(ike_sa);
+
+ if (script == NULL)
+ {
+ return TRUE;
+ }
+
+ enumerator = child_sa->create_policy_enumerator(child_sa);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ char command[1024];
+ char *my_client, *other_client, *my_client_mask, *other_client_mask;
+ char *pos, *virtual_ip, *iface;
+ bool is_host, is_ipv6;
+ FILE *shell;
+
+ /* get subnet/bits from string */
+ if (asprintf(&my_client, "%R", my_ts) < 0)
+ {
+ my_client = NULL;
+ }
+ pos = strchr(my_client, '/');
+ *pos = '\0';
+ my_client_mask = pos + 1;
+ pos = strchr(my_client_mask, '[');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+ if (asprintf(&other_client, "%R", other_ts) < 0)
+ {
+ other_client = NULL;
+ }
+ pos = strchr(other_client, '/');
+ *pos = '\0';
+ other_client_mask = pos + 1;
+ pos = strchr(other_client_mask, '[');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+
+ if (vip)
+ {
+ if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
+ {
+ virtual_ip = NULL;
+ }
+ }
+ else
+ {
+ if (asprintf(&virtual_ip, "") < 0)
+ {
+ virtual_ip = NULL;
+ }
+ }
+
+ if (up)
+ {
+ iface = charon->kernel_interface->get_interface(
+ charon->kernel_interface, me);
+ if (iface)
+ {
+ cache_iface(this, child_sa->get_reqid(child_sa), iface);
+ }
+ }
+ else
+ {
+ iface = uncache_iface(this, child_sa->get_reqid(child_sa));
+ }
+
+ /* determine IPv4/IPv6 and client/host situation */
+ is_host = my_ts->is_host(my_ts, me);
+ is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) :
+ (my_ts->get_type(my_ts) == TS_IPV6_ADDR_RANGE);
+
+ /* build the command with all env variables.
+ * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
+ */
+ snprintf(command, sizeof(command),
+ "2>&1 "
+ "PLUTO_VERSION='1.1' "
+ "PLUTO_VERB='%s%s%s' "
+ "PLUTO_CONNECTION='%s' "
+ "PLUTO_INTERFACE='%s' "
+ "PLUTO_REQID='%u' "
+ "PLUTO_ME='%H' "
+ "PLUTO_MY_ID='%Y' "
+ "PLUTO_MY_CLIENT='%s/%s' "
+ "PLUTO_MY_CLIENT_NET='%s' "
+ "PLUTO_MY_CLIENT_MASK='%s' "
+ "PLUTO_MY_PORT='%u' "
+ "PLUTO_MY_PROTOCOL='%u' "
+ "PLUTO_PEER='%H' "
+ "PLUTO_PEER_ID='%Y' "
+ "PLUTO_PEER_CLIENT='%s/%s' "
+ "PLUTO_PEER_CLIENT_NET='%s' "
+ "PLUTO_PEER_CLIENT_MASK='%s' "
+ "PLUTO_PEER_PORT='%u' "
+ "PLUTO_PEER_PROTOCOL='%u' "
+ "%s"
+ "%s"
+ "%s",
+ up ? "up" : "down",
+ is_host ? "-host" : "-client",
+ is_ipv6 ? "-v6" : "",
+ config->get_name(config),
+ iface ? iface : "unknown",
+ child_sa->get_reqid(child_sa),
+ me, ike_sa->get_my_id(ike_sa),
+ my_client, my_client_mask,
+ my_client, my_client_mask,
+ my_ts->get_from_port(my_ts),
+ my_ts->get_protocol(my_ts),
+ other, ike_sa->get_other_id(ike_sa),
+ other_client, other_client_mask,
+ other_client, other_client_mask,
+ other_ts->get_from_port(other_ts),
+ other_ts->get_protocol(other_ts),
+ virtual_ip,
+ config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+ script);
+ free(my_client);
+ free(other_client);
+ free(virtual_ip);
+ free(iface);
+
+ DBG3(DBG_CHD, "running updown script: %s", command);
+ shell = popen(command, "r");
+
+ if (shell == NULL)
+ {
+ DBG1(DBG_CHD, "could not execute updown script '%s'", script);
+ return TRUE;
+ }
+
+ while (TRUE)
+ {
+ char resp[128];
+
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_CHD, "error reading output from updown script");
+ }
+ break;
+ }
+ else
+ {
+ char *e = resp + strlen(resp);
+ if (e > resp && e[-1] == '\n')
+ { /* trim trailing '\n' */
+ e[-1] = '\0';
+ }
+ DBG1(DBG_CHD, "updown: %s", resp);
+ }
+ }
+ pclose(shell);
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+}
+
+METHOD(updown_listener_t, destroy, void,
+ private_updown_listener_t *this)
+{
+ this->iface_cache->destroy(this->iface_cache);
+ free(this);
+}
+
+/**
+ * See header
+ */
+updown_listener_t *updown_listener_create()
+{
+ private_updown_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener.child_updown = _child_updown,
+ .destroy = _destroy,
+ },
+ .iface_cache = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/updown/updown_listener.h b/src/libcharon/plugins/updown/updown_listener.h
new file mode 100644
index 000000000..5b866c4e5
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_listener.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup updown_listener updown_listener
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_LISTENER_H_
+#define UPDOWN_LISTENER_H_
+
+#include <bus/bus.h>
+
+typedef struct updown_listener_t updown_listener_t;
+
+/**
+ * Listener which invokes the scripts on CHILD_SA up/down.
+ */
+struct updown_listener_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a updown_listener_t.
+ */
+ void (*destroy)(updown_listener_t *this);
+};
+
+/**
+ * Create a updown_listener instance.
+ */
+updown_listener_t *updown_listener_create();
+
+#endif /** UPDOWN_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c
new file mode 100644
index 000000000..9d0591e62
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_plugin.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "updown_plugin.h"
+#include "updown_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_updown_plugin_t private_updown_plugin_t;
+
+/**
+ * private data of updown plugin
+ */
+struct private_updown_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ updown_plugin_t public;
+
+ /**
+ * Listener interface, listens to CHILD_SA state changes
+ */
+ updown_listener_t *listener;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_updown_plugin_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *updown_plugin_create()
+{
+ private_updown_plugin_t *this = malloc_thing(private_updown_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->listener = updown_listener_create();
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/updown/updown_plugin.h b/src/libcharon/plugins/updown/updown_plugin.h
new file mode 100644
index 000000000..abcb953a0
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 updown updown
+ * @ingroup cplugins
+ *
+ * @defgroup updown_plugin updown_plugin
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_PLUGIN_H_
+#define UPDOWN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct updown_plugin_t updown_plugin_t;
+
+/**
+ * Updown firewall script invocation plugin, compatible to pluto ones.
+ */
+struct updown_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** UPDOWN_PLUGIN_H_ @}*/
diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c
new file mode 100644
index 000000000..45ace9312
--- /dev/null
+++ b/src/libcharon/processing/jobs/acquire_job.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2006-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 "acquire_job.h"
+
+#include <daemon.h>
+
+
+typedef struct private_acquire_job_t private_acquire_job_t;
+
+/**
+ * Private data of an acquire_job_t object.
+ */
+struct private_acquire_job_t {
+ /**
+ * Public acquire_job_t interface.
+ */
+ acquire_job_t public;
+
+ /**
+ * reqid of the child to rekey
+ */
+ u_int32_t reqid;
+
+ /**
+ * acquired source traffic selector
+ */
+ traffic_selector_t *src_ts;
+
+ /**
+ * acquired destination traffic selector
+ */
+ traffic_selector_t *dst_ts;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_acquire_job_t *this)
+{
+ DESTROY_IF(this->src_ts);
+ DESTROY_IF(this->dst_ts);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_acquire_job_t *this)
+{
+ charon->traps->acquire(charon->traps, this->reqid,
+ this->src_ts, this->dst_ts);
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+acquire_job_t *acquire_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
+{
+ private_acquire_job_t *this = malloc_thing(private_acquire_job_t);
+
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ this->reqid = reqid;
+ this->src_ts = src_ts;
+ this->dst_ts = dst_ts;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/acquire_job.h b/src/libcharon/processing/jobs/acquire_job.h
new file mode 100644
index 000000000..eff79a9b0
--- /dev/null
+++ b/src/libcharon/processing/jobs/acquire_job.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 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 acquire_job acquire_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef ACQUIRE_JOB_H_
+#define ACQUIRE_JOB_H_
+
+typedef struct acquire_job_t acquire_job_t;
+
+#include <library.h>
+#include <selectors/traffic_selector.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing an ACQUIRE Job.
+ *
+ * This job initiates a CHILD SA on kernel request.
+ */
+struct acquire_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type ACQUIRE.
+ *
+ * @param reqid reqid of the trapped CHILD_SA to acquire
+ * @param src_ts source traffic selector
+ * @param dst_ts destination traffic selector
+ * @return acquire_job_t object
+ */
+acquire_job_t *acquire_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts);
+
+#endif /** REKEY_CHILD_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/callback_job.c b/src/libcharon/processing/jobs/callback_job.c
new file mode 100644
index 000000000..45e49112e
--- /dev/null
+++ b/src/libcharon/processing/jobs/callback_job.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "callback_job.h"
+
+#include <semaphore.h>
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+typedef struct private_callback_job_t private_callback_job_t;
+
+/**
+ * Private data of an callback_job_t Object.
+ */
+struct private_callback_job_t {
+ /**
+ * Public callback_job_t interface.
+ */
+ callback_job_t public;
+
+ /**
+ * Callback to call on execution
+ */
+ callback_job_cb_t callback;
+
+ /**
+ * parameter to supply to callback
+ */
+ void *data;
+
+ /**
+ * cleanup function for data
+ */
+ callback_job_cleanup_t cleanup;
+
+ /**
+ * thread of the job, if running
+ */
+ thread_t *thread;
+
+ /**
+ * mutex to access jobs interna
+ */
+ mutex_t *mutex;
+
+ /**
+ * list of asociated child jobs
+ */
+ linked_list_t *children;
+
+ /**
+ * parent of this job, or NULL
+ */
+ private_callback_job_t *parent;
+
+ /**
+ * TRUE if the job got cancelled
+ */
+ bool cancelled;
+
+ /**
+ * condvar to synchronize the cancellation/destruction of the job
+ */
+ condvar_t *destroyable;
+
+ /**
+ * semaphore to synchronize the termination of the assigned thread.
+ *
+ * separately allocated during cancellation, so that we can wait on it
+ * without risking that it gets freed too early during destruction.
+ */
+ sem_t *terminated;
+};
+
+/**
+ * unregister a child from its parent, if any.
+ * note: this->mutex has to be locked
+ */
+static void unregister(private_callback_job_t *this)
+{
+ if (this->parent)
+ {
+ this->parent->mutex->lock(this->parent->mutex);
+ if (this->parent->cancelled && !this->cancelled)
+ {
+ /* if the parent has been cancelled but we have not yet, we do not
+ * unregister until we got cancelled by the parent. */
+ this->parent->mutex->unlock(this->parent->mutex);
+ this->destroyable->wait(this->destroyable, this->mutex);
+ this->parent->mutex->lock(this->parent->mutex);
+ }
+ this->parent->children->remove(this->parent->children, this, NULL);
+ this->parent->mutex->unlock(this->parent->mutex);
+ this->parent = NULL;
+ }
+}
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_callback_job_t *this)
+{
+ this->mutex->lock(this->mutex);
+ unregister(this);
+ if (this->cleanup)
+ {
+ this->cleanup(this->data);
+ }
+ if (this->terminated)
+ {
+ sem_post(this->terminated);
+ }
+ this->children->destroy(this->children);
+ this->destroyable->destroy(this->destroyable);
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * Implementation of callback_job_t.cancel.
+ */
+static void cancel(private_callback_job_t *this)
+{
+ callback_job_t *child;
+ sem_t *terminated = NULL;
+
+ this->mutex->lock(this->mutex);
+ this->cancelled = TRUE;
+ /* terminate children */
+ while (this->children->get_first(this->children, (void**)&child) == SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ child->cancel(child);
+ this->mutex->lock(this->mutex);
+ }
+ if (this->thread)
+ {
+ /* terminate the thread, if there is currently one executing the job.
+ * we wait for its termination using a semaphore */
+ this->thread->cancel(this->thread);
+ terminated = this->terminated = malloc_thing(sem_t);
+ sem_init(terminated, 0, 0);
+ }
+ else
+ {
+ /* if the job is currently queued, it gets terminated later.
+ * we can't wait, because it might not get executed at all.
+ * we also unregister the queued job manually from its parent (the
+ * others get unregistered during destruction) */
+ unregister(this);
+ }
+ this->destroyable->signal(this->destroyable);
+ this->mutex->unlock(this->mutex);
+
+ if (terminated)
+ {
+ sem_wait(terminated);
+ sem_destroy(terminated);
+ free(terminated);
+ }
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_callback_job_t *this)
+{
+ bool cleanup = FALSE, requeue = FALSE;
+
+ thread_cleanup_push((thread_cleanup_t)destroy, this);
+
+ this->mutex->lock(this->mutex);
+ this->thread = thread_current();
+ this->mutex->unlock(this->mutex);
+
+ while (TRUE)
+ {
+ this->mutex->lock(this->mutex);
+ if (this->cancelled)
+ {
+ this->mutex->unlock(this->mutex);
+ cleanup = TRUE;
+ break;
+ }
+ this->mutex->unlock(this->mutex);
+ switch (this->callback(this->data))
+ {
+ case JOB_REQUEUE_DIRECT:
+ continue;
+ case JOB_REQUEUE_FAIR:
+ {
+ requeue = TRUE;
+ break;
+ }
+ case JOB_REQUEUE_NONE:
+ default:
+ {
+ cleanup = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ this->mutex->lock(this->mutex);
+ this->thread = NULL;
+ this->mutex->unlock(this->mutex);
+ /* manually create a cancellation point to avoid that a cancelled thread
+ * goes back into the thread pool */
+ thread_cancellation_point();
+ if (requeue)
+ {
+ charon->processor->queue_job(charon->processor,
+ &this->public.job_interface);
+ }
+ thread_cleanup_pop(cleanup);
+}
+
+/*
+ * Described in header.
+ */
+callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
+ callback_job_cleanup_t cleanup,
+ callback_job_t *parent)
+{
+ private_callback_job_t *this = malloc_thing(private_callback_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+ this->public.cancel = (void(*)(callback_job_t*))cancel;
+
+ /* private variables */
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->callback = cb;
+ this->data = data;
+ this->cleanup = cleanup;
+ this->thread = 0;
+ this->children = linked_list_create();
+ this->parent = (private_callback_job_t*)parent;
+ this->cancelled = FALSE;
+ this->destroyable = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->terminated = NULL;
+
+ /* register us at parent */
+ if (parent)
+ {
+ this->parent->mutex->lock(this->parent->mutex);
+ this->parent->children->insert_last(this->parent->children, this);
+ this->parent->mutex->unlock(this->parent->mutex);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/callback_job.h b/src/libcharon/processing/jobs/callback_job.h
new file mode 100644
index 000000000..62da1edd1
--- /dev/null
+++ b/src/libcharon/processing/jobs/callback_job.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup callback_job callback_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef CALLBACK_JOB_H_
+#define CALLBACK_JOB_H_
+
+typedef struct callback_job_t callback_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+
+typedef enum job_requeue_t job_requeue_t;
+
+/**
+ * Job requeueing policy
+ *
+ * The job requeueing policy defines how a job is handled when the callback
+ * function returns.
+ */
+enum job_requeue_t {
+
+ /**
+ * Do not requeue job, destroy it
+ */
+ JOB_REQUEUE_NONE,
+
+ /**
+ * Reque the job fairly, meaning it has to requeue as any other job
+ */
+ JOB_REQUEUE_FAIR,
+
+ /**
+ * Reexecute the job directly, without the need of requeueing it
+ */
+ JOB_REQUEUE_DIRECT,
+};
+
+/**
+ * The callback function to use for the callback job.
+ *
+ * This is the function to use as callback for a callback job. It receives
+ * a parameter supplied to the callback jobs constructor.
+ *
+ * @param data param supplied to job
+ * @return requeing policy how to requeue the job
+ */
+typedef job_requeue_t (*callback_job_cb_t)(void *data);
+
+/**
+ * Cleanup function to use for data cleanup.
+ *
+ * The callback has an optional user argument which receives data. However,
+ * this data may be cleaned up if it is allocated. This is the function
+ * to supply to the constructor.
+ *
+ * @param data param supplied to job
+ * @return requeing policy how to requeue the job
+ */
+typedef void (*callback_job_cleanup_t)(void *data);
+
+/**
+ * Class representing an callback Job.
+ *
+ * This is a special job which allows a simple callback function to
+ * be executed by a thread of the thread pool. This allows simple execution
+ * of asynchronous methods, without to manage threads.
+ */
+struct callback_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+
+ /**
+ * Cancel the job's thread and wait for its termination. This only works
+ * reliably for jobs that always use JOB_REQUEUE_FAIR or JOB_REQUEUE_DIRECT,
+ * otherwise the job may already be destroyed when cancel is called. */
+ void (*cancel)(callback_job_t *this);
+};
+
+/**
+ * Creates a callback job.
+ *
+ * The cleanup function is called when the job gets destroyed to destroy
+ * the associated data.
+ * If parent is not NULL, the specified job gets an association. Whenever
+ * the parent gets cancelled (or runs out), all of its children are cancelled,
+ * too.
+ *
+ * @param cb callback to call from the processor
+ * @param data user data to supply to callback
+ * @param cleanup destructor for data on destruction, or NULL
+ * @param parent parent of this job
+ * @return callback_job_t object
+ */
+callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
+ callback_job_cleanup_t cleanup,
+ callback_job_t *parent);
+
+#endif /** CALLBACK_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c
new file mode 100644
index 000000000..ca55721f2
--- /dev/null
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2006 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 "delete_child_sa_job.h"
+
+#include <daemon.h>
+
+
+typedef struct private_delete_child_sa_job_t private_delete_child_sa_job_t;
+
+/**
+ * Private data of an delete_child_sa_job_t object.
+ */
+struct private_delete_child_sa_job_t {
+ /**
+
+ * Public delete_child_sa_job_t interface.
+ */
+ delete_child_sa_job_t public;
+
+ /**
+ * reqid of the CHILD_SA
+ */
+ u_int32_t reqid;
+
+ /**
+ * protocol of the CHILD_SA (ESP/AH)
+ */
+ protocol_id_t protocol;
+
+ /**
+ * inbound SPI of the CHILD_SA
+ */
+ u_int32_t spi;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_delete_child_sa_job_t *this)
+{
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_delete_child_sa_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for delete",
+ this->reqid);
+ }
+ else
+ {
+ ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi);
+
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
+ protocol_id_t protocol,
+ u_int32_t spi)
+{
+ private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ /* private variables */
+ this->reqid = reqid;
+ this->protocol = protocol;
+ this->spi = spi;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h
new file mode 100644
index 000000000..662a7b7c7
--- /dev/null
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006 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 delete_child_sa_job delete_child_sa_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef DELETE_CHILD_SA_JOB_H_
+#define DELETE_CHILD_SA_JOB_H_
+
+typedef struct delete_child_sa_job_t delete_child_sa_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+#include <config/proposal.h>
+
+
+/**
+ * Class representing an DELETE_CHILD_SA Job.
+ *
+ * This job initiates the delete of a CHILD SA.
+ */
+struct delete_child_sa_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type DELETE_CHILD_SA.
+ *
+ * The CHILD_SA is identified by its reqid, protocol (AH/ESP) and its
+ * inbound SPI.
+ *
+ * @param reqid reqid of the CHILD_SA, as used in kernel
+ * @param protocol protocol of the CHILD_SA
+ * @param spi security parameter index of the CHILD_SA
+ * @return delete_child_sa_job_t object
+ */
+delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
+ protocol_id_t protocol,
+ u_int32_t spi);
+
+#endif /** DELETE_CHILD_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c
new file mode 100644
index 000000000..dffd08ba3
--- /dev/null
+++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "delete_ike_sa_job.h"
+
+#include <daemon.h>
+
+typedef struct private_delete_ike_sa_job_t private_delete_ike_sa_job_t;
+
+/**
+ * Private data of an delete_ike_sa_job_t Object
+ */
+struct private_delete_ike_sa_job_t {
+ /**
+ * public delete_ike_sa_job_t interface
+ */
+ delete_ike_sa_job_t public;
+
+ /**
+ * ID of the ike_sa to delete
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * Should the IKE_SA be deleted if it is in ESTABLISHED state?
+ */
+ bool delete_if_established;
+};
+
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_delete_ike_sa_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_delete_ike_sa_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa)
+ {
+ if (ike_sa->get_state(ike_sa) == IKE_PASSIVE)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return destroy(this);
+ }
+ if (this->delete_if_established)
+ {
+ if (ike_sa->delete(ike_sa) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ else
+ {
+ /* destroy only if not ESTABLISHED */
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_JOB, "deleting half open IKE_SA after timeout");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ }
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id,
+ bool delete_if_established)
+{
+ private_delete_ike_sa_job_t *this = malloc_thing(private_delete_ike_sa_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t *)) destroy;;
+
+ /* private variables */
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ this->delete_if_established = delete_if_established;
+
+ return &(this->public);
+}
diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.h b/src/libcharon/processing/jobs/delete_ike_sa_job.h
new file mode 100644
index 000000000..f641deea3
--- /dev/null
+++ b/src/libcharon/processing/jobs/delete_ike_sa_job.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup delete_child_sa_job delete_child_sa_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef DELETE_IKE_SA_JOB_H_
+#define DELETE_IKE_SA_JOB_H_
+
+typedef struct delete_ike_sa_job_t delete_ike_sa_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+
+
+/**
+ * Class representing an DELETE_IKE_SA Job.
+ *
+ * This job is responsible for deleting established or half open IKE_SAs.
+ * A half open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED
+ * state.
+ */
+struct delete_ike_sa_job_t {
+
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type DELETE_IKE_SA.
+ *
+ * @param ike_sa_id id of the IKE_SA to delete
+ * @param delete_if_established should the IKE_SA be deleted if it is established?
+ * @return created delete_ike_sa_job_t object
+ */
+delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id,
+ bool delete_if_established);
+
+#endif /** DELETE_IKE_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c
new file mode 100644
index 000000000..13fc5e3d0
--- /dev/null
+++ b/src/libcharon/processing/jobs/inactivity_job.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2010 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 "inactivity_job.h"
+
+#include <daemon.h>
+
+typedef struct private_inactivity_job_t private_inactivity_job_t;
+
+/**
+ * Private data of an inactivity_job_t object.
+ */
+struct private_inactivity_job_t {
+
+ /**
+ * Public inactivity_job_t interface.
+ */
+ inactivity_job_t public;
+
+ /**
+ * Reqid of CHILD_SA to check
+ */
+ u_int32_t reqid;
+
+ /**
+ * Inactivity timeout
+ */
+ u_int32_t timeout;
+
+ /**
+ * Close IKE_SA if last remaining CHILD inactive?
+ */
+ bool close_ike;
+};
+
+METHOD(job_t, destroy, void,
+ private_inactivity_job_t *this)
+{
+ free(this);
+}
+
+METHOD(job_t, execute, void,
+ private_inactivity_job_t *this)
+{
+ ike_sa_t *ike_sa;
+ bool rescheduled = FALSE;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ if (ike_sa)
+ {
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ u_int32_t delete = 0;
+ protocol_id_t proto = 0;
+ int children = 0;
+ status_t status = SUCCESS;
+
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ if (child_sa->get_reqid(child_sa) == this->reqid)
+ {
+ time_t in, out, diff;
+
+ child_sa->get_usestats(child_sa, TRUE, &in, NULL);
+ child_sa->get_usestats(child_sa, FALSE, &out, NULL);
+
+ diff = time_monotonic(NULL) - max(in, out);
+
+ if (diff >= this->timeout)
+ {
+ delete = child_sa->get_spi(child_sa, TRUE);
+ proto = child_sa->get_protocol(child_sa);
+ }
+ else
+ {
+ charon->scheduler->schedule_job(charon->scheduler,
+ &this->public.job_interface, this->timeout - diff);
+ rescheduled = TRUE;
+ }
+ }
+ children++;
+ }
+ iterator->destroy(iterator);
+
+ if (delete)
+ {
+ if (children == 1 && this->close_ike)
+ {
+ DBG1(DBG_JOB, "deleting IKE_SA after %d seconds "
+ "of CHILD_SA inactivity", this->timeout);
+ status = ike_sa->delete(ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
+ "of inactivity", this->timeout);
+ status = ike_sa->delete_child_sa(ike_sa, proto, delete);
+ }
+ }
+ if (status == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ if (!rescheduled)
+ {
+ destroy(this);
+ }
+}
+
+/**
+ * See header
+ */
+inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout,
+ bool close_ike)
+{
+ private_inactivity_job_t *this;
+
+ INIT(this,
+ .public.job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ .reqid = reqid,
+ .timeout = timeout,
+ .close_ike = close_ike,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/inactivity_job.h b/src/libcharon/processing/jobs/inactivity_job.h
new file mode 100644
index 000000000..9c9daced8
--- /dev/null
+++ b/src/libcharon/processing/jobs/inactivity_job.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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 inactivity_job inactivity_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef INACTIVITY_JOB_H_
+#define INACTIVITY_JOB_H_
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+typedef struct inactivity_job_t inactivity_job_t;
+
+/**
+ * Job checking for inactivity of CHILD_SA to close them.
+ *
+ * The inactivity job reschedules itself to check CHILD_SAs prediodically.
+ */
+struct inactivity_job_t {
+
+ /**
+ * Implements job_t.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Create a inactivity_job instance.
+ *
+ * @param reqid reqid of CHILD_SA to check for inactivity
+ * @param timeout inactivity timeout in s
+ * @param close_ike close IKE_SA if the last remaining CHILD_SA is inactive?
+ * @return inactivity checking job
+ */
+inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout,
+ bool close_ike);
+
+#endif /** INACTIVITY_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
new file mode 100644
index 000000000..ffe8755e2
--- /dev/null
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007-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 "initiate_mediation_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_initiate_mediation_job_t private_initiate_mediation_job_t;
+
+/**
+ * Private data of an initiate_mediation_job_t Object
+ */
+struct private_initiate_mediation_job_t {
+ /**
+ * public initiate_mediation_job_t interface
+ */
+ initiate_mediation_job_t public;
+
+ /**
+ * ID of the IKE_SA of the mediated connection.
+ */
+ ike_sa_id_t *mediated_sa_id;
+
+ /**
+ * ID of the IKE_SA of the mediation connection.
+ */
+ ike_sa_id_t *mediation_sa_id;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_initiate_mediation_job_t *this)
+{
+ DESTROY_IF(this->mediation_sa_id);
+ DESTROY_IF(this->mediated_sa_id);
+ free(this);
+}
+
+/**
+ * Callback to handle initiation of mediation connection
+ */
+static bool initiate_callback(private_initiate_mediation_job_t *this,
+ debug_t group, level_t level, ike_sa_t *ike_sa,
+ char *format, va_list args)
+{
+ if (ike_sa && !this->mediation_sa_id)
+ {
+ this->mediation_sa_id = ike_sa->get_id(ike_sa);
+ this->mediation_sa_id = this->mediation_sa_id->clone(this->mediation_sa_id);
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void initiate(private_initiate_mediation_job_t *this)
+{
+ ike_sa_t *mediated_sa, *mediation_sa;
+ peer_cfg_t *mediated_cfg, *mediation_cfg;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth_cfg;
+
+ mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "initiating mediation connection");
+ mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa);
+ mediated_cfg->get_ref(mediated_cfg);
+
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
+
+ mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg);
+ mediation_cfg->get_ref(mediation_cfg);
+
+ enumerator = mediation_cfg->create_auth_cfg_enumerator(mediation_cfg,
+ TRUE);
+ if (!enumerator->enumerate(enumerator, &auth_cfg) ||
+ auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY) == NULL)
+ {
+ mediated_cfg->destroy(mediated_cfg);
+ mediation_cfg->destroy(mediation_cfg);
+ enumerator->destroy(enumerator);
+ destroy(this);
+ return;
+ }
+ enumerator->destroy(enumerator);
+
+ if (charon->connect_manager->check_and_register(charon->connect_manager,
+ auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY),
+ mediated_cfg->get_peer_id(mediated_cfg),
+ this->mediated_sa_id))
+ {
+ mediated_cfg->destroy(mediated_cfg);
+ mediation_cfg->destroy(mediation_cfg);
+
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "mediation with the same peer is already in "
+ "progress, queued");
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, mediated_sa);
+ }
+ destroy(this);
+ return;
+ }
+ /* we need an additional reference because initiate consumes one */
+ mediation_cfg->get_ref(mediation_cfg);
+
+ if (charon->controller->initiate(charon->controller, mediation_cfg,
+ NULL, (controller_cb_t)initiate_callback, this) != SUCCESS)
+ {
+ mediation_cfg->destroy(mediation_cfg);
+ mediated_cfg->destroy(mediated_cfg);
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "initiating mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediated_sa);
+ }
+ destroy(this);
+ return;
+ }
+ mediation_cfg->destroy(mediation_cfg);
+
+ mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->mediation_sa_id);
+ if (mediation_sa)
+ {
+ if (mediation_sa->initiate_mediation(mediation_sa,
+ mediated_cfg) != SUCCESS)
+ {
+ mediated_cfg->destroy(mediated_cfg);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediation_sa);
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "establishing mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediated_sa);
+ }
+ destroy(this);
+ return;
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ mediation_sa);
+ }
+ mediated_cfg->destroy(mediated_cfg);
+ }
+ destroy(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void reinitiate(private_initiate_mediation_job_t *this)
+{
+ ike_sa_t *mediated_sa, *mediation_sa;
+ peer_cfg_t *mediated_cfg;
+
+ mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa);
+ mediated_cfg->get_ref(mediated_cfg);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
+
+ mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->mediation_sa_id);
+ if (mediation_sa)
+ {
+ if (mediation_sa->initiate_mediation(mediation_sa,
+ mediated_cfg) != SUCCESS)
+ {
+ DBG1(DBG_JOB, "initiating mediated connection '%s' failed",
+ mediated_cfg->get_name(mediated_cfg));
+ mediated_cfg->destroy(mediated_cfg);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager,
+ mediation_sa);
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager,
+ this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "establishing mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager,
+ mediated_sa);
+ }
+ destroy(this);
+ return;
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ mediation_sa);
+ }
+
+ mediated_cfg->destroy(mediated_cfg);
+ }
+ destroy(this);
+}
+
+/**
+ * Creates an empty job
+ */
+static private_initiate_mediation_job_t *initiate_mediation_job_create_empty()
+{
+ private_initiate_mediation_job_t *this = malloc_thing(private_initiate_mediation_job_t);
+
+ /* interface functions */
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ /* private variables */
+ this->mediation_sa_id = NULL;
+ this->mediated_sa_id = NULL;
+
+ return this;
+}
+
+/*
+ * Described in header
+ */
+initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id)
+{
+ private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty();
+
+ this->public.job_interface.execute = (void (*) (job_t *)) initiate;
+
+ this->mediated_sa_id = ike_sa_id->clone(ike_sa_id);
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+initiate_mediation_job_t *reinitiate_mediation_job_create(ike_sa_id_t *mediation_sa_id,
+ ike_sa_id_t *mediated_sa_id)
+{
+ private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty();
+
+ this->public.job_interface.execute = (void (*) (job_t *)) reinitiate;
+
+ this->mediation_sa_id = mediation_sa_id->clone(mediation_sa_id);
+ this->mediated_sa_id = mediated_sa_id->clone(mediated_sa_id);
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.h b/src/libcharon/processing/jobs/initiate_mediation_job.h
new file mode 100644
index 000000000..fddb1dd7b
--- /dev/null
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007-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 initiate_mediation_job initiate_mediation_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef INITIATE_MEDIATION_JOB_H_
+#define INITIATE_MEDIATION_JOB_H_
+
+typedef struct initiate_mediation_job_t initiate_mediation_job_t;
+
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+/**
+ * Class representing a INITIATE_MEDIATION Job.
+ *
+ * This job will initiate a mediation on behalf of a mediated connection.
+ * If required the mediation connection is established.
+ */
+struct initiate_mediation_job_t {
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type INITIATE_MEDIATION.
+ *
+ * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned)
+ * @return job object
+ */
+initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id);
+
+/**
+ * Creates a special job of type INITIATE_MEDIATION that reinitiates a
+ * specific connection.
+ *
+ * @param mediation_sa_id identification of the mediation sa (gets cloned)
+ * @param mediated_sa_id identification of the mediated sa (gets cloned)
+ * @return job object
+ */
+initiate_mediation_job_t *reinitiate_mediation_job_create(
+ ike_sa_id_t *mediation_sa_id,
+ ike_sa_id_t *mediated_sa_id);
+
+#endif /** INITIATE_MEDIATION_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/job.h b/src/libcharon/processing/jobs/job.h
new file mode 100644
index 000000000..0f1c16ebe
--- /dev/null
+++ b/src/libcharon/processing/jobs/job.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup job job
+ * @{ @ingroup jobs
+ */
+
+#ifndef JOB_H_
+#define JOB_H_
+
+typedef struct job_t job_t;
+
+#include <library.h>
+
+/**
+ * Job-Interface as it is stored in the job queue.
+ */
+struct job_t {
+
+ /**
+ * Execute a job.
+ *
+ * The processing facility executes a job using this method. Jobs are
+ * one-shot, they destroy themself after execution, so don't use a job
+ * once it has been executed.
+ */
+ void (*execute) (job_t *this);
+
+ /**
+ * Destroy a job.
+ *
+ * Is only called whenever a job was not executed (e.g. due daemon shutdown).
+ * After execution, jobs destroy themself.
+ */
+ void (*destroy) (job_t *job);
+};
+
+#endif /** JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/mediation_job.c b/src/libcharon/processing/jobs/mediation_job.c
new file mode 100644
index 000000000..b5b8af3b3
--- /dev/null
+++ b/src/libcharon/processing/jobs/mediation_job.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007 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 "mediation_job.h"
+
+#include <encoding/payloads/endpoint_notify.h>
+#include <daemon.h>
+
+
+typedef struct private_mediation_job_t private_mediation_job_t;
+
+/**
+ * Private data of an mediation_job_t Object
+ */
+struct private_mediation_job_t {
+ /**
+ * public mediation_job_t interface
+ */
+ mediation_job_t public;
+
+ /**
+ * ID of target peer.
+ */
+ identification_t *target;
+
+ /**
+ * ID of the source peer.
+ */
+ identification_t *source;
+
+ /**
+ * ME_CONNECTID
+ */
+ chunk_t connect_id;
+
+ /**
+ * ME_CONNECTKEY
+ */
+ chunk_t connect_key;
+
+ /**
+ * Submitted endpoints
+ */
+ linked_list_t *endpoints;
+
+ /**
+ * Is this a callback job?
+ */
+ bool callback;
+
+ /**
+ * Is this a response?
+ */
+ bool response;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_mediation_job_t *this)
+{
+ DESTROY_IF(this->target);
+ DESTROY_IF(this->source);
+ chunk_free(&this->connect_id);
+ chunk_free(&this->connect_key);
+ DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy));
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_mediation_job_t *this)
+{
+ ike_sa_id_t *target_sa_id;
+
+ target_sa_id = charon->mediation_manager->check(charon->mediation_manager, this->target);
+
+ if (target_sa_id)
+ {
+ ike_sa_t *target_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ target_sa_id);
+ if (target_sa)
+ {
+ if (this->callback)
+ {
+ /* send callback to a peer */
+ if (target_sa->callback(target_sa, this->source) != SUCCESS)
+ {
+ DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed",
+ this->source, this->target);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
+ destroy(this);
+ return;
+ }
+ }
+ else
+ {
+ /* normal mediation between two peers */
+ if (target_sa->relay(target_sa, this->source, this->connect_id,
+ this->connect_key, this->endpoints, this->response) != SUCCESS)
+ {
+ DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed",
+ this->source, this->target);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
+ /* FIXME: notify the initiator */
+ destroy(this);
+ return;
+ }
+ }
+
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
+ }
+ else
+ {
+ DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
+ "SA not found", this->source, this->target);
+ }
+ }
+ else
+ {
+ DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
+ "peer is not online anymore", this->source, this->target);
+ }
+ destroy(this);
+}
+
+/**
+ * Creates an empty mediation job
+ */
+static private_mediation_job_t *mediation_job_create_empty()
+{
+ private_mediation_job_t *this = malloc_thing(private_mediation_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ /* private variables */
+ this->target = NULL;
+ this->source = NULL;
+ this->callback = FALSE;
+ this->connect_id = chunk_empty;
+ this->connect_key = chunk_empty;
+ this->endpoints = NULL;
+ this->response = FALSE;
+
+ return this;
+}
+
+/*
+ * Described in header
+ */
+mediation_job_t *mediation_job_create(identification_t *peer_id,
+ identification_t *requester, chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response)
+{
+ private_mediation_job_t *this = mediation_job_create_empty();
+
+ this->target = peer_id->clone(peer_id);
+ this->source = requester->clone(requester);
+ this->connect_id = chunk_clone(connect_id);
+ this->connect_key = chunk_clone(connect_key);
+ this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
+ this->response = response;
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+mediation_job_t *mediation_callback_job_create(identification_t *requester,
+ identification_t *peer_id)
+{
+ private_mediation_job_t *this = mediation_job_create_empty();
+
+ this->target = requester->clone(requester);
+ this->source = peer_id->clone(peer_id);
+ this->callback = TRUE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/mediation_job.h b/src/libcharon/processing/jobs/mediation_job.h
new file mode 100644
index 000000000..0574c65eb
--- /dev/null
+++ b/src/libcharon/processing/jobs/mediation_job.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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 mediation_job mediation_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef MEDIATION_JOB_H_
+#define MEDIATION_JOB_H_
+
+typedef struct mediation_job_t mediation_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <utils/identification.h>
+#include <utils/linked_list.h>
+
+/**
+ * Class representing a MEDIATION Job.
+ *
+ * This job handles the mediation on the mediation server.
+ */
+struct mediation_job_t {
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type MEDIATION.
+ *
+ * Parameters get cloned.
+ *
+ * @param peer_id ID of the requested peer
+ * @param requester ID of the requesting peer
+ * @param connect_id content of ME_CONNECTID (could be NULL)
+ * @param connect_key content of ME_CONNECTKEY
+ * @param endpoints list of submitted endpoints
+ * @param response TRUE if this is a response
+ * @return job object
+ */
+mediation_job_t *mediation_job_create(identification_t *peer_id,
+ identification_t *requester, chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response);
+
+
+/**
+ * Creates a special job of type MEDIATION that is used to send a callback
+ * notification to a peer.
+ *
+ * Parameters get cloned.
+ *
+ * @param requester ID of the waiting peer
+ * @param peer_id ID of the requested peer
+ * @return job object
+ */
+mediation_job_t *mediation_callback_job_create(identification_t *requester,
+ identification_t *peer_id);
+
+#endif /** MEDIATION_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
new file mode 100644
index 000000000..05f47340c
--- /dev/null
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "migrate_job.h"
+
+#include <daemon.h>
+
+#include <config/child_cfg.h>
+
+
+typedef struct private_migrate_job_t private_migrate_job_t;
+
+/**
+ * Private data of a migrate_job_t object.
+ */
+struct private_migrate_job_t {
+ /**
+ * Public migrate_job_t interface.
+ */
+ migrate_job_t public;
+
+ /**
+ * reqid of the CHILD_SA if it already exists
+ */
+ u_int32_t reqid;
+
+ /**
+ * source traffic selector
+ */
+ traffic_selector_t *src_ts;
+
+ /**
+ * destination traffic selector
+ */
+ traffic_selector_t *dst_ts;
+
+ /**
+ * local host address to be used for IKE
+ */
+ host_t *local;
+
+ /**
+ * remote host address to be used for IKE
+ */
+ host_t *remote;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_migrate_job_t *this)
+{
+ DESTROY_IF(this->src_ts);
+ DESTROY_IF(this->dst_ts);
+ DESTROY_IF(this->local);
+ DESTROY_IF(this->remote);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_migrate_job_t *this)
+{
+ ike_sa_t *ike_sa = NULL;
+
+ if (this->reqid)
+ {
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ }
+ if (ike_sa)
+ {
+ iterator_t *children;
+ child_sa_t *child_sa;
+ host_t *host;
+
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (child_sa->get_reqid(child_sa) == this->reqid)
+ {
+ break;
+ }
+ }
+ children->destroy(children);
+ DBG2(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid);
+
+ ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
+
+ host = this->local->clone(this->local);
+ host->set_port(host, IKEV2_UDP_PORT);
+ ike_sa->set_my_host(ike_sa, host);
+
+ host = this->remote->clone(this->remote);
+ host->set_port(host, IKEV2_UDP_PORT);
+ ike_sa->set_other_host(ike_sa, host);
+
+ if (child_sa->update(child_sa, this->local, this->remote,
+ ike_sa->get_virtual_ip(ike_sa, TRUE),
+ ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+migrate_job_t *migrate_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t dir,
+ host_t *local, host_t *remote)
+{
+ private_migrate_job_t *this = malloc_thing(private_migrate_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ /* private variables */
+ this->reqid = reqid;
+ this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts;
+ this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts;
+ this->local = local;
+ this->remote = remote;
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/migrate_job.h b/src/libcharon/processing/jobs/migrate_job.h
new file mode 100644
index 000000000..de313d517
--- /dev/null
+++ b/src/libcharon/processing/jobs/migrate_job.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup migrate_job migrate_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef MIGRATE_JOB_H_
+#define MIGRATE_JOB_H_
+
+typedef struct migrate_job_t migrate_job_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <selectors/traffic_selector.h>
+#include <kernel/kernel_ipsec.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing a MIGRATE Job.
+ *
+ * This job sets a routed CHILD_SA for an existing IPsec policy.
+ */
+struct migrate_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type MIGRATE.
+ *
+ * We use the reqid or the traffic selectors to find a matching CHILD_SA.
+ *
+ * @param reqid reqid of the CHILD_SA to acquire
+ * @param src_ts source traffic selector to be used in the policy
+ * @param dst_ts destination traffic selector to be used in the policy
+ * @param dir direction of the policy (in|out)
+ * @param local local host address to be used in the IKE_SA
+ * @param remote remote host address to be used in the IKE_SA
+ * @return migrate_job_t object
+ */
+migrate_job_t *migrate_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t dir, host_t *local, host_t *remote);
+
+#endif /** MIGRATE_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c
new file mode 100644
index 000000000..a47d48e38
--- /dev/null
+++ b/src/libcharon/processing/jobs/process_message_job.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "process_message_job.h"
+
+#include <daemon.h>
+
+typedef struct private_process_message_job_t private_process_message_job_t;
+
+/**
+ * Private data of an process_message_job_t Object
+ */
+struct private_process_message_job_t {
+ /**
+ * public process_message_job_t interface
+ */
+ process_message_job_t public;
+
+ /**
+ * Message associated with this job
+ */
+ message_t *message;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_process_message_job_t *this)
+{
+ this->message->destroy(this->message);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_process_message_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+#ifdef ME
+ /* 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)
+ {
+ /* theoretically this could also be an error message
+ * see RFC 4306, section 1.5. */
+ DBG1(DBG_NET, "received unencrypted informational: from %#H to %#H",
+ this->message->get_source(this->message),
+ this->message->get_destination(this->message));
+ charon->connect_manager->process_check(charon->connect_manager, this->message);
+ destroy(this);
+ return;
+ }
+#endif /* ME */
+
+ ike_sa = charon->ike_sa_manager->checkout_by_message(charon->ike_sa_manager,
+ this->message);
+ if (ike_sa)
+ {
+ DBG1(DBG_NET, "received packet: from %#H to %#H",
+ this->message->get_source(this->message),
+ this->message->get_destination(this->message));
+ if (ike_sa->process_message(ike_sa, this->message) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+process_message_job_t *process_message_job_create(message_t *message)
+{
+ private_process_message_job_t *this = malloc_thing(private_process_message_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void(*)(job_t*))destroy;
+
+ /* private variables */
+ this->message = message;
+
+ return &(this->public);
+}
diff --git a/src/libcharon/processing/jobs/process_message_job.h b/src/libcharon/processing/jobs/process_message_job.h
new file mode 100644
index 000000000..5e3f44d1f
--- /dev/null
+++ b/src/libcharon/processing/jobs/process_message_job.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup process_message_job process_message_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef PROCESS_MESSAGE_JOB_H_
+#define PROCESS_MESSAGE_JOB_H_
+
+typedef struct process_message_job_t process_message_job_t;
+
+#include <library.h>
+#include <encoding/message.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing an PROCESS_MESSAGE job.
+ */
+struct process_message_job_t {
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type PROCESS_MESSAGE.
+ *
+ * @param message message to process
+ * @return created process_message_job_t object
+ */
+process_message_job_t *process_message_job_create(message_t *message);
+
+#endif /** PROCESS_MESSAGE_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c
new file mode 100644
index 000000000..b797d181e
--- /dev/null
+++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2006 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 "rekey_child_sa_job.h"
+
+#include <daemon.h>
+
+
+typedef struct private_rekey_child_sa_job_t private_rekey_child_sa_job_t;
+
+/**
+ * Private data of an rekey_child_sa_job_t object.
+ */
+struct private_rekey_child_sa_job_t {
+ /**
+ * Public rekey_child_sa_job_t interface.
+ */
+ rekey_child_sa_job_t public;
+
+ /**
+ * reqid of the child to rekey
+ */
+ u_int32_t reqid;
+
+ /**
+ * protocol of the CHILD_SA (ESP/AH)
+ */
+ protocol_id_t protocol;
+
+ /**
+ * inbound SPI of the CHILD_SA
+ */
+ u_int32_t spi;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_rekey_child_sa_job_t *this)
+{
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_rekey_child_sa_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG2(DBG_JOB, "CHILD_SA with reqid %d not found for rekeying",
+ this->reqid);
+ }
+ else
+ {
+ ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid,
+ protocol_id_t protocol,
+ u_int32_t spi)
+{
+ private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ /* private variables */
+ this->reqid = reqid;
+ this->protocol = protocol;
+ this->spi = spi;
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.h b/src/libcharon/processing/jobs/rekey_child_sa_job.h
new file mode 100644
index 000000000..62887d6b9
--- /dev/null
+++ b/src/libcharon/processing/jobs/rekey_child_sa_job.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 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 rekey_child_sa_job rekey_child_sa_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef REKEY_CHILD_SA_JOB_H_
+#define REKEY_CHILD_SA_JOB_H_
+
+typedef struct rekey_child_sa_job_t rekey_child_sa_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+#include <config/proposal.h>
+
+/**
+ * Class representing an REKEY_CHILD_SA Job.
+ *
+ * This job initiates the rekeying of a CHILD SA.
+ */
+struct rekey_child_sa_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type REKEY_CHILD_SA.
+ *
+ * The CHILD_SA is identified by its protocol (AH/ESP) and its
+ * inbound SPI.
+ *
+ * @param reqid reqid of the CHILD_SA to rekey
+ * @param protocol protocol of the CHILD_SA
+ * @param spi security parameter index of the CHILD_SA
+ * @return rekey_child_sa_job_t object
+ */
+rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid,
+ protocol_id_t protocol,
+ u_int32_t spi);
+#endif /** REKEY_CHILD_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
new file mode 100644
index 000000000..5ec0b1b88
--- /dev/null
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 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 "rekey_ike_sa_job.h"
+
+#include <daemon.h>
+
+typedef struct private_rekey_ike_sa_job_t private_rekey_ike_sa_job_t;
+
+/**
+ * Private data of an rekey_ike_sa_job_t object.
+ */
+struct private_rekey_ike_sa_job_t {
+ /**
+ * Public rekey_ike_sa_job_t interface.
+ */
+ rekey_ike_sa_job_t public;
+
+ /**
+ * ID of the IKE_SA to rekey
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * force reauthentication of the peer (full IKE_SA setup)
+ */
+ bool reauth;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_rekey_ike_sa_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_rekey_ike_sa_job_t *this)
+{
+ ike_sa_t *ike_sa;
+ status_t status = SUCCESS;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa == NULL)
+ {
+ DBG2(DBG_JOB, "IKE_SA to rekey not found");
+ }
+ else
+ {
+ if (this->reauth)
+ {
+ status = ike_sa->reauth(ike_sa);
+ }
+ else
+ {
+ status = ike_sa->rekey(ike_sa);
+ }
+
+ if (status == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth)
+{
+ private_rekey_ike_sa_job_t *this = malloc_thing(private_rekey_ike_sa_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ /* private variables */
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ this->reauth = reauth;
+
+ return &(this->public);
+}
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.h b/src/libcharon/processing/jobs/rekey_ike_sa_job.h
new file mode 100644
index 000000000..a5c1028aa
--- /dev/null
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 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 rekey_ike_sa_job rekey_ike_sa_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef REKEY_IKE_SA_JOB_H_
+#define REKEY_IKE_SA_JOB_H_
+
+typedef struct rekey_ike_sa_job_t rekey_ike_sa_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing an REKEY_IKE_SA Job.
+ *
+ * This job initiates the rekeying of an IKE_SA.
+ */
+struct rekey_ike_sa_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type REKEY_IKE_SA.
+ *
+ * @param ike_sa_id ID of the IKE_SA to rekey
+ * @param reauth TRUE to reauthenticate peer, FALSE for rekeying only
+ * @return rekey_ike_sa_job_t object
+ */
+rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth);
+
+#endif /** REKEY_IKE_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c
new file mode 100644
index 000000000..fc787f208
--- /dev/null
+++ b/src/libcharon/processing/jobs/retransmit_job.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "retransmit_job.h"
+
+#include <daemon.h>
+
+typedef struct private_retransmit_job_t private_retransmit_job_t;
+
+/**
+ * Private data of an retransmit_job_t Object.
+ */
+struct private_retransmit_job_t {
+ /**
+ * Public retransmit_job_t interface.
+ */
+ retransmit_job_t public;
+
+ /**
+ * Message ID of the request to resend.
+ */
+ u_int32_t message_id;
+
+ /**
+ * ID of the IKE_SA which the message belongs to.
+ */
+ ike_sa_id_t *ike_sa_id;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_retransmit_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_retransmit_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa)
+ {
+ if (ike_sa->retransmit(ike_sa, this->message_id) == DESTROY_ME)
+ {
+ /* retransmitted to many times, giving up */
+ 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);
+ }
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header.
+ */
+retransmit_job_t *retransmit_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id)
+{
+ private_retransmit_job_t *this = malloc_thing(private_retransmit_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ /* private variables */
+ this->message_id = message_id;
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/retransmit_job.h b/src/libcharon/processing/jobs/retransmit_job.h
new file mode 100644
index 000000000..c8c13479b
--- /dev/null
+++ b/src/libcharon/processing/jobs/retransmit_job.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup retransmit_job retransmit_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef RETRANSMIT_JOB_H_
+#define RETRANSMIT_JOB_H_
+
+typedef struct retransmit_job_t retransmit_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+/**
+ * Class representing an retransmit Job.
+ *
+ * This job is scheduled every time a request is sent over the
+ * wire. If the response to the request is not received at schedule
+ * time, the retransmission will be initiated.
+ */
+struct retransmit_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type retransmit.
+ *
+ * @param message_id message_id of the request to resend
+ * @param ike_sa_id identification of the ike_sa as ike_sa_id_t
+ * @return retransmit_job_t object
+ */
+retransmit_job_t *retransmit_job_create(u_int32_t message_id,
+ ike_sa_id_t *ike_sa_id);
+
+#endif /** RETRANSMIT_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c
new file mode 100644
index 000000000..adc884a8a
--- /dev/null
+++ b/src/libcharon/processing/jobs/roam_job.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+
+#include "roam_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_roam_job_t private_roam_job_t;
+
+/**
+ * Private data of an roam_job_t Object
+ */
+struct private_roam_job_t {
+ /**
+ * public roam_job_t interface
+ */
+ roam_job_t public;
+
+ /**
+ * has the address list changed, or the routing only?
+ */
+ bool address;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_roam_job_t *this)
+{
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_roam_job_t *this)
+{
+ ike_sa_t *ike_sa;
+ linked_list_t *list;
+ ike_sa_id_t *id;
+ enumerator_t *enumerator;
+
+ /* enumerator over all IKE_SAs gives us no way to checkin_and_destroy
+ * after a DESTROY_ME, so we check out each available IKE_SA by hand. */
+ list = linked_list_create();
+ enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ id = ike_sa->get_id(ike_sa);
+ list->insert_last(list, id->clone(id));
+ }
+ enumerator->destroy(enumerator);
+
+ while (list->remove_last(list, (void**)&id) == SUCCESS)
+ {
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
+ if (ike_sa)
+ {
+ if (ike_sa->roam(ike_sa, this->address) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ id->destroy(id);
+ }
+ list->destroy(list);
+
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+roam_job_t *roam_job_create(bool address)
+{
+ private_roam_job_t *this = malloc_thing(private_roam_job_t);
+
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ this->address = address;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/roam_job.h b/src/libcharon/processing/jobs/roam_job.h
new file mode 100644
index 000000000..55bdf2b28
--- /dev/null
+++ b/src/libcharon/processing/jobs/roam_job.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup roam_job roam_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef ROAM_JOB_H_
+#define ROAM_JOB_H_
+
+typedef struct roam_job_t roam_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+
+/**
+ * A job to inform IKE_SAs about changed local address setup.
+ *
+ * If a local address appears or disappears, the kernel fires this job to
+ * update all IKE_SAs.
+ */
+struct roam_job_t {
+
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job to inform IKE_SAs about an updated address list.
+ *
+ * @param address TRUE if address list changed, FALSE if routing changed
+ * @return initiate_ike_sa_job_t object
+ */
+roam_job_t *roam_job_create(bool address);
+
+#endif /** ROAM_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c
new file mode 100644
index 000000000..1c2da52b8
--- /dev/null
+++ b/src/libcharon/processing/jobs/send_dpd_job.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * 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 <stdlib.h>
+
+#include "send_dpd_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_send_dpd_job_t private_send_dpd_job_t;
+
+/**
+ * Private data of an send_dpd_job_t Object
+ */
+struct private_send_dpd_job_t {
+ /**
+ * public send_dpd_job_t interface
+ */
+ send_dpd_job_t public;
+
+ /**
+ * ID of the IKE_SA which the message belongs to.
+ */
+ ike_sa_id_t *ike_sa_id;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_send_dpd_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_send_dpd_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa)
+ {
+ if (ike_sa->send_dpd(ike_sa) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id)
+{
+ private_send_dpd_job_t *this = malloc_thing(private_send_dpd_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ /* private variables */
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/send_dpd_job.h b/src/libcharon/processing/jobs/send_dpd_job.h
new file mode 100644
index 000000000..8078a38bc
--- /dev/null
+++ b/src/libcharon/processing/jobs/send_dpd_job.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * 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 send_dpd_job send_dpd_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef SEND_DPD_JOB_H_
+#define SEND_DPD_JOB_H_
+
+typedef struct send_dpd_job_t send_dpd_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+/**
+ * Class representing a SEND_DPD Job.
+ *
+ * Job to periodically send a Dead Peer Detection (DPD) request,
+ * ie. an IKE request with no payloads other than the encrypted payload
+ * required by the syntax.
+ */
+struct send_dpd_job_t {
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type SEND_DPD.
+ *
+ * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned)
+ * @return initiate_ike_sa_job_t object
+ */
+send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id);
+
+#endif /** SEND_DPD_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c
new file mode 100644
index 000000000..3d02cea2e
--- /dev/null
+++ b/src/libcharon/processing/jobs/send_keepalive_job.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * 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 <stdlib.h>
+
+#include "send_keepalive_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_send_keepalive_job_t private_send_keepalive_job_t;
+
+/**
+ * Private data of an send_keepalive_job_t Object
+ */
+struct private_send_keepalive_job_t {
+ /**
+ * public send_keepalive_job_t interface
+ */
+ send_keepalive_job_t public;
+
+ /**
+ * ID of the IKE_SA which the message belongs to.
+ */
+ ike_sa_id_t *ike_sa_id;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_send_keepalive_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_send_keepalive_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa)
+ {
+ ike_sa->send_keepalive(ike_sa);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id)
+{
+ private_send_keepalive_job_t *this = malloc_thing(private_send_keepalive_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ /* private variables */
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/send_keepalive_job.h b/src/libcharon/processing/jobs/send_keepalive_job.h
new file mode 100644
index 000000000..cda83cd7e
--- /dev/null
+++ b/src/libcharon/processing/jobs/send_keepalive_job.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * 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 send_keepalive_job send_keepalive_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef SEND_KEEPALIVE_JOB_H_
+#define SEND_KEEPALIVE_JOB_H_
+
+typedef struct send_keepalive_job_t send_keepalive_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+/**
+ * Class representing a SEND_KEEPALIVE Job.
+ *
+ * This job will send a NAT keepalive packet if the IKE SA is still alive,
+ * and reinsert itself into the event queue.
+ */
+struct send_keepalive_job_t {
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type SEND_KEEPALIVE.
+ *
+ * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned)
+ * @return initiate_ike_sa_job_t object
+ */
+send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id);
+
+#endif /** SEND_KEEPALIVE_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c
new file mode 100644
index 000000000..17dce2548
--- /dev/null
+++ b/src/libcharon/processing/jobs/update_sa_job.c
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+
+#include "update_sa_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_update_sa_job_t private_update_sa_job_t;
+
+/**
+ * Private data of an update_sa_job_t Object
+ */
+struct private_update_sa_job_t {
+ /**
+ * public update_sa_job_t interface
+ */
+ update_sa_job_t public;
+
+ /**
+ * reqid of the CHILD_SA
+ */
+ u_int32_t reqid;
+
+ /**
+ * New SA address and port
+ */
+ host_t *new;
+};
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_update_sa_job_t *this)
+{
+ this->new->destroy(this->new);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_update_sa_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for update", this->reqid);
+ }
+ else
+ {
+ /* we update only if other host is NATed, but not our */
+ if (ike_sa->has_condition(ike_sa, COND_NAT_THERE) &&
+ !ike_sa->has_condition(ike_sa, COND_NAT_HERE))
+ {
+ ike_sa->update_hosts(ike_sa, NULL, this->new);
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new)
+{
+ private_update_sa_job_t *this = malloc_thing(private_update_sa_job_t);
+
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+
+ this->reqid = reqid;
+ this->new = new;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/update_sa_job.h b/src/libcharon/processing/jobs/update_sa_job.h
new file mode 100644
index 000000000..11d1ac9b6
--- /dev/null
+++ b/src/libcharon/processing/jobs/update_sa_job.h
@@ -0,0 +1,50 @@
+/*
+ * 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 update_sa_job update_sa_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef UPDATE_SA_JOB_H_
+#define UPDATE_SA_JOB_H_
+
+typedef struct update_sa_job_t update_sa_job_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Update the addresses of an IKE and its CHILD_SAs.
+ */
+struct update_sa_job_t {
+
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job to update IKE and CHILD_SA addresses.
+ *
+ * @param reqid reqid of the CHILD_SA
+ * @param new new address and port
+ * @return update_sa_job_t object
+ */
+update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new);
+
+#endif /** UPDATE_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/processor.c b/src/libcharon/processing/processor.c
new file mode 100644
index 000000000..d5774af26
--- /dev/null
+++ b/src/libcharon/processing/processor.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "processor.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_processor_t private_processor_t;
+
+/**
+ * Private data of processor_t class.
+ */
+struct private_processor_t {
+ /**
+ * Public processor_t interface.
+ */
+ processor_t public;
+
+ /**
+ * Number of running threads
+ */
+ u_int total_threads;
+
+ /**
+ * Desired number of threads
+ */
+ u_int desired_threads;
+
+ /**
+ * Number of threads waiting for work
+ */
+ u_int idle_threads;
+
+ /**
+ * All threads managed in the pool (including threads that have been
+ * cancelled, this allows to join them during destruction)
+ */
+ linked_list_t *threads;
+
+ /**
+ * The jobs are stored in a linked list
+ */
+ linked_list_t *list;
+
+ /**
+ * access to linked_list is locked through this mutex
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to wait for new jobs
+ */
+ condvar_t *job_added;
+
+ /**
+ * Condvar to wait for terminated threads
+ */
+ condvar_t *thread_terminated;
+};
+
+static void process_jobs(private_processor_t *this);
+
+/**
+ * restart a terminated thread
+ */
+static void restart(private_processor_t *this)
+{
+ thread_t *thread;
+
+ DBG2(DBG_JOB, "terminated worker thread, ID: %u", thread_current_id());
+
+ /* respawn thread if required */
+ this->mutex->lock(this->mutex);
+ if (this->desired_threads < this->total_threads ||
+ (thread = thread_create((thread_main_t)process_jobs, this)) == NULL)
+ {
+ this->total_threads--;
+ this->thread_terminated->signal(this->thread_terminated);
+ }
+ else
+ {
+ this->threads->insert_last(this->threads, thread);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Process queued jobs, called by the worker threads
+ */
+static void process_jobs(private_processor_t *this)
+{
+ /* worker threads are not cancellable by default */
+ thread_cancelability(FALSE);
+
+ DBG2(DBG_JOB, "started worker thread, ID: %u", thread_current_id());
+
+ this->mutex->lock(this->mutex);
+ while (this->desired_threads >= this->total_threads)
+ {
+ job_t *job;
+
+ if (this->list->get_count(this->list) == 0)
+ {
+ this->idle_threads++;
+ this->job_added->wait(this->job_added, this->mutex);
+ this->idle_threads--;
+ continue;
+ }
+ this->list->remove_first(this->list, (void**)&job);
+ this->mutex->unlock(this->mutex);
+ /* terminated threads are restarted, so we have a constant pool */
+ thread_cleanup_push((thread_cleanup_t)restart, this);
+ job->execute(job);
+ thread_cleanup_pop(FALSE);
+ this->mutex->lock(this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+ restart(this);
+}
+
+/**
+ * Implementation of processor_t.get_total_threads.
+ */
+static u_int get_total_threads(private_processor_t *this)
+{
+ u_int count;
+ this->mutex->lock(this->mutex);
+ count = this->total_threads;
+ this->mutex->unlock(this->mutex);
+ return count;
+}
+
+/**
+ * Implementation of processor_t.get_idle_threads.
+ */
+static u_int get_idle_threads(private_processor_t *this)
+{
+ u_int count;
+ this->mutex->lock(this->mutex);
+ count = this->idle_threads;
+ this->mutex->unlock(this->mutex);
+ return count;
+}
+
+/**
+ * implements processor_t.get_job_load
+ */
+static u_int get_job_load(private_processor_t *this)
+{
+ u_int load;
+ this->mutex->lock(this->mutex);
+ load = this->list->get_count(this->list);
+ this->mutex->unlock(this->mutex);
+ return load;
+}
+
+/**
+ * implements function processor_t.queue_job
+ */
+static void queue_job(private_processor_t *this, job_t *job)
+{
+ this->mutex->lock(this->mutex);
+ this->list->insert_last(this->list, job);
+ this->job_added->signal(this->job_added);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of processor_t.set_threads.
+ */
+static void set_threads(private_processor_t *this, u_int count)
+{
+ this->mutex->lock(this->mutex);
+ if (count > this->total_threads)
+ { /* increase thread count */
+ int i;
+ thread_t *current;
+
+ this->desired_threads = count;
+ DBG1(DBG_JOB, "spawning %d worker threads", count - this->total_threads);
+ for (i = this->total_threads; i < count; i++)
+ {
+ current = thread_create((thread_main_t)process_jobs, this);
+ if (current)
+ {
+ this->threads->insert_last(this->threads, current);
+ this->total_threads++;
+ }
+ }
+ }
+ else if (count < this->total_threads)
+ { /* decrease thread count */
+ this->desired_threads = count;
+ }
+ this->job_added->broadcast(this->job_added);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of processor_t.destroy.
+ */
+static void destroy(private_processor_t *this)
+{
+ thread_t *current;
+ set_threads(this, 0);
+ this->mutex->lock(this->mutex);
+ while (this->total_threads > 0)
+ {
+ this->job_added->broadcast(this->job_added);
+ this->thread_terminated->wait(this->thread_terminated, this->mutex);
+ }
+ while (this->threads->remove_first(this->threads,
+ (void**)&current) == SUCCESS)
+ {
+ current->join(current);
+ }
+ this->mutex->unlock(this->mutex);
+ this->thread_terminated->destroy(this->thread_terminated);
+ this->job_added->destroy(this->job_added);
+ this->mutex->destroy(this->mutex);
+ this->list->destroy_offset(this->list, offsetof(job_t, destroy));
+ this->threads->destroy(this->threads);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+processor_t *processor_create(size_t pool_size)
+{
+ private_processor_t *this = malloc_thing(private_processor_t);
+
+ this->public.get_total_threads = (u_int(*)(processor_t*))get_total_threads;
+ this->public.get_idle_threads = (u_int(*)(processor_t*))get_idle_threads;
+ this->public.get_job_load = (u_int(*)(processor_t*))get_job_load;
+ this->public.queue_job = (void(*)(processor_t*, job_t*))queue_job;
+ this->public.set_threads = (void(*)(processor_t*, u_int))set_threads;
+ this->public.destroy = (void(*)(processor_t*))destroy;
+
+ this->list = linked_list_create();
+ this->threads = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->job_added = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->thread_terminated = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->total_threads = 0;
+ this->desired_threads = 0;
+ this->idle_threads = 0;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/processor.h b/src/libcharon/processing/processor.h
new file mode 100644
index 000000000..5bf8cf573
--- /dev/null
+++ b/src/libcharon/processing/processor.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup processor processor
+ * @{ @ingroup processing
+ */
+
+#ifndef PROCESSOR_H_
+#define PROCESSOR_H_
+
+typedef struct processor_t processor_t;
+
+#include <stdlib.h>
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+/**
+ * The processor uses threads to process queued jobs.
+ */
+struct processor_t {
+
+ /**
+ * Get the total number of threads used by the processor.
+ *
+ * @return size of thread pool
+ */
+ u_int (*get_total_threads) (processor_t *this);
+
+ /**
+ * Get the number of threads currently waiting.
+ *
+ * @return number of idle threads
+ */
+ u_int (*get_idle_threads) (processor_t *this);
+
+ /**
+ * Get the number of queued jobs.
+ *
+ * @returns number of items in queue
+ */
+ u_int (*get_job_load) (processor_t *this);
+
+ /**
+ * Adds a job to the queue.
+ *
+ * This function is non blocking and adds a job_t to the queue.
+ *
+ * @param job job to add to the queue
+ */
+ void (*queue_job) (processor_t *this, job_t *job);
+
+ /**
+ * Set the number of threads to use in the processor.
+ *
+ * If the number of threads is smaller than number of currently running
+ * threads, thread count is decreased. Use 0 to disable the processor.
+ * This call blocks if it decreases thread count until threads have
+ * terminated, so make sure there are not too many blocking jobs.
+ *
+ * @param count number of threads to allocate
+ */
+ void (*set_threads)(processor_t *this, u_int count);
+
+ /**
+ * Destroy a processor object.
+ */
+ void (*destroy) (processor_t *processor);
+};
+
+/**
+ * Create the thread pool without any threads.
+ *
+ * Use the set_threads method to start processing jobs.
+ *
+ * @return processor_t object
+ */
+processor_t *processor_create();
+
+#endif /** PROCESSOR_H_ @}*/
diff --git a/src/libcharon/processing/scheduler.c b/src/libcharon/processing/scheduler.c
new file mode 100644
index 000000000..345af502a
--- /dev/null
+++ b/src/libcharon/processing/scheduler.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+
+#include "scheduler.h"
+
+#include <daemon.h>
+#include <processing/processor.h>
+#include <processing/jobs/callback_job.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+
+/* the initial size of the heap */
+#define HEAP_SIZE_DEFAULT 64
+
+typedef struct event_t event_t;
+
+/**
+ * Event containing a job and a schedule time
+ */
+struct event_t {
+ /**
+ * Time to fire the event.
+ */
+ timeval_t time;
+
+ /**
+ * Every event has its assigned job.
+ */
+ job_t *job;
+};
+
+/**
+ * destroy an event and its job
+ */
+static void event_destroy(event_t *event)
+{
+ event->job->destroy(event->job);
+ free(event);
+}
+
+typedef struct private_scheduler_t private_scheduler_t;
+
+/**
+ * Private data of a scheduler_t object.
+ */
+struct private_scheduler_t {
+
+ /**
+ * Public part of a scheduler_t object.
+ */
+ scheduler_t public;
+
+ /**
+ * Job which queues scheduled jobs to the processor.
+ */
+ callback_job_t *job;
+
+ /**
+ * The heap in which the events are stored.
+ */
+ event_t **heap;
+
+ /**
+ * The size of the heap.
+ */
+ u_int heap_size;
+
+ /**
+ * The number of scheduled events.
+ */
+ u_int event_count;
+
+ /**
+ * Exclusive access to list
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to wait for next job.
+ */
+ condvar_t *condvar;
+};
+
+/**
+ * Comparse two timevals, return >0 if a > b, <0 if a < b and =0 if equal
+ */
+static int timeval_cmp(timeval_t *a, timeval_t *b)
+{
+ if (a->tv_sec > b->tv_sec)
+ {
+ return 1;
+ }
+ if (a->tv_sec < b->tv_sec)
+ {
+ return -1;
+ }
+ if (a->tv_usec > b->tv_usec)
+ {
+ return 1;
+ }
+ if (a->tv_usec < b->tv_usec)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Returns the top event without removing it. Returns NULL if the heap is empty.
+ */
+static event_t *peek_event(private_scheduler_t *this)
+{
+ return this->event_count > 0 ? this->heap[1] : NULL;
+}
+
+/**
+ * Removes the top event from the heap and returns it. Returns NULL if the heap
+ * is empty.
+ */
+static event_t *remove_event(private_scheduler_t *this)
+{
+ event_t *event, *top;
+ if (!this->event_count)
+ {
+ return NULL;
+ }
+
+ /* store the value to return */
+ event = this->heap[1];
+ /* move the bottom event to the top */
+ top = this->heap[1] = this->heap[this->event_count];
+
+ if (--this->event_count > 1)
+ {
+ /* seep down the top event */
+ u_int position = 1;
+ while ((position << 1) <= this->event_count)
+ {
+ u_int child = position << 1;
+
+ if ((child + 1) <= this->event_count &&
+ timeval_cmp(&this->heap[child + 1]->time,
+ &this->heap[child]->time) < 0)
+ {
+ /* the "right" child is smaller */
+ child++;
+ }
+
+ if (timeval_cmp(&top->time, &this->heap[child]->time) <= 0)
+ {
+ /* the top event fires before the smaller of the two children,
+ * stop */
+ break;
+ }
+
+ /* swap with the smaller child */
+ this->heap[position] = this->heap[child];
+ position = child;
+ }
+ this->heap[position] = top;
+ }
+ return event;
+}
+
+/**
+ * Get events from the queue and pass it to the processor
+ */
+static job_requeue_t schedule(private_scheduler_t * this)
+{
+ timeval_t now;
+ event_t *event;
+ bool timed = FALSE, oldstate;
+
+ this->mutex->lock(this->mutex);
+
+ time_monotonic(&now);
+
+ if ((event = peek_event(this)) != NULL)
+ {
+ if (timeval_cmp(&now, &event->time) >= 0)
+ {
+ remove_event(this);
+ this->mutex->unlock(this->mutex);
+ DBG2(DBG_JOB, "got event, queuing job for execution");
+ charon->processor->queue_job(charon->processor, event->job);
+ free(event);
+ return JOB_REQUEUE_DIRECT;
+ }
+ timersub(&event->time, &now, &now);
+ if (now.tv_sec)
+ {
+ DBG2(DBG_JOB, "next event in %ds %dms, waiting",
+ now.tv_sec, now.tv_usec/1000);
+ }
+ else
+ {
+ DBG2(DBG_JOB, "next event in %dms, waiting", now.tv_usec/1000);
+ }
+ timed = TRUE;
+ }
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ oldstate = thread_cancelability(TRUE);
+
+ if (timed)
+ {
+ this->condvar->timed_wait_abs(this->condvar, this->mutex, event->time);
+ }
+ else
+ {
+ DBG2(DBG_JOB, "no events, waiting");
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ thread_cancelability(oldstate);
+ thread_cleanup_pop(TRUE);
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implements scheduler_t.get_job_load
+ */
+static u_int get_job_load(private_scheduler_t *this)
+{
+ int count;
+ this->mutex->lock(this->mutex);
+ count = this->event_count;
+ this->mutex->unlock(this->mutex);
+ return count;
+}
+
+/**
+ * Implements scheduler_t.schedule_job_tv.
+ */
+static void schedule_job_tv(private_scheduler_t *this, job_t *job, timeval_t tv)
+{
+ event_t *event;
+ u_int position;
+
+ event = malloc_thing(event_t);
+ event->job = job;
+ event->time = tv;
+
+ this->mutex->lock(this->mutex);
+
+ this->event_count++;
+ if (this->event_count > this->heap_size)
+ {
+ /* double the size of the heap */
+ this->heap_size <<= 1;
+ this->heap = (event_t**)realloc(this->heap,
+ (this->heap_size + 1) * sizeof(event_t*));
+ }
+ /* "put" the event to the bottom */
+ position = this->event_count;
+
+ /* then bubble it up */
+ while (position > 1 && timeval_cmp(&this->heap[position >> 1]->time,
+ &event->time) > 0)
+ {
+ /* parent has to be fired after the new event, move up */
+ this->heap[position] = this->heap[position >> 1];
+ position >>= 1;
+ }
+ this->heap[position] = event;
+
+ this->condvar->signal(this->condvar);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implements scheduler_t.schedule_job.
+ */
+static void schedule_job(private_scheduler_t *this, job_t *job, u_int32_t s)
+{
+ timeval_t tv;
+
+ time_monotonic(&tv);
+ tv.tv_sec += s;
+
+ schedule_job_tv(this, job, tv);
+}
+
+/**
+ * Implements scheduler_t.schedule_job_ms.
+ */
+static void schedule_job_ms(private_scheduler_t *this, job_t *job, u_int32_t ms)
+{
+ timeval_t tv, add;
+
+ time_monotonic(&tv);
+ add.tv_sec = ms / 1000;
+ add.tv_usec = (ms % 1000) * 1000;
+
+ timeradd(&tv, &add, &tv);
+
+ schedule_job_tv(this, job, tv);
+}
+
+/**
+ * Implementation of scheduler_t.destroy.
+ */
+static void destroy(private_scheduler_t *this)
+{
+ event_t *event;
+ this->job->cancel(this->job);
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
+ while ((event = remove_event(this)) != NULL)
+ {
+ event_destroy(event);
+ }
+ free(this->heap);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+scheduler_t * scheduler_create()
+{
+ private_scheduler_t *this = malloc_thing(private_scheduler_t);
+
+ this->public.get_job_load = (u_int (*) (scheduler_t *this)) get_job_load;
+ this->public.schedule_job = (void (*) (scheduler_t *this, job_t *job, u_int32_t s)) schedule_job;
+ this->public.schedule_job_ms = (void (*) (scheduler_t *this, job_t *job, u_int32_t ms)) schedule_job_ms;
+ this->public.schedule_job_tv = (void (*) (scheduler_t *this, job_t *job, timeval_t tv)) schedule_job_tv;
+ this->public.destroy = (void(*)(scheduler_t*)) destroy;
+
+ /* Note: the root of the heap is at index 1 */
+ this->event_count = 0;
+ this->heap_size = HEAP_SIZE_DEFAULT;
+ this->heap = (event_t**)calloc(this->heap_size + 1, sizeof(event_t*));
+
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+ this->job = callback_job_create((callback_job_cb_t)schedule, this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/scheduler.h b/src/libcharon/processing/scheduler.h
new file mode 100644
index 000000000..5f5d2a563
--- /dev/null
+++ b/src/libcharon/processing/scheduler.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup scheduler scheduler
+ * @{ @ingroup processing
+ */
+
+#ifndef SCHEDULER_H_
+#define SCHEDULER_H_
+
+typedef struct scheduler_t scheduler_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+/**
+ * The scheduler queues timed events which are then passed to the processor.
+ *
+ * The scheduler is implemented as a heap. A heap is a special kind of tree-
+ * based data structure that satisfies the following property: if B is a child
+ * node of A, then key(A) >= (or <=) key(B). So either the element with the
+ * greatest (max-heap) or the smallest (min-heap) key is the root of the heap.
+ * We use a min-heap whith the key being the absolute unix time at which an
+ * event is scheduled. So the root is always the event that will fire next.
+ *
+ * An earlier implementation of the scheduler used a sorted linked list to store
+ * the events. That had the advantage that removing the next event was extremely
+ * fast, also, adding an event scheduled before or after all other events was
+ * equally fast (all in O(1)). The problem was, though, that adding an event
+ * in-between got slower, as the number of events grew larger (O(n)).
+ * For each connection there could be several events: IKE-rekey, NAT-keepalive,
+ * retransmissions, expire (half-open), and others. So a gateway that probably
+ * has to handle thousands of concurrent connnections has to be able to queue a
+ * large number of events as fast as possible. Locking makes this even worse, to
+ * provide thread-safety, no events can be processed, while an event is queued,
+ * so making the insertion fast is even more important.
+ *
+ * That's the advantage of the heap. Adding an element to the heap can be
+ * achieved in O(log n) - on the other hand, removing the root node also
+ * requires O(log n) operations. Consider 10000 queued events. Inserting a new
+ * event in the list implementation required up to 10000 comparisons. In the
+ * heap implementation, the worst case is about 13.3 comparisons. That's a
+ * drastic improvement.
+ *
+ * The implementation itself uses a binary tree mapped to a one-based array to
+ * store the elements. This reduces storage overhead and simplifies navigation:
+ * the children of the node at position n are at position 2n and 2n+1 (likewise
+ * the parent node of the node at position n is at position [n/2]). Thus,
+ * navigating up and down the tree is reduced to simple index computations.
+ *
+ * Adding an element to the heap works as follows: The heap is always filled
+ * from left to right, until a row is full, then the next row is filled. Mapped
+ * to an array this gets as simple as putting the new element to the first free
+ * position. In a one-based array that position equals the number of elements
+ * currently stored in the heap. Then the heap property has to be restored, i.e.
+ * the new element has to be "bubbled up" the tree until the parent node's key
+ * is smaller or the element got the new root of the tree.
+ *
+ * Removing the next event from the heap works similarly. The event itself is
+ * the root node and stored at position 1 of the array. After removing it, the
+ * root has to be replaced and the heap property has to be restored. This is
+ * done by moving the bottom element (last row, rightmost element) to the root
+ * and then "seep it down" by swapping it with child nodes until none of the
+ * children has a smaller key or it is again a leaf node.
+ */
+struct scheduler_t {
+
+ /**
+ * Adds a event to the queue, using a relative time offset in s.
+ *
+ * @param job job to schedule
+ * @param time relative time to schedule job, in s
+ */
+ void (*schedule_job) (scheduler_t *this, job_t *job, u_int32_t s);
+
+ /**
+ * Adds a event to the queue, using a relative time offset in ms.
+ *
+ * @param job job to schedule
+ * @param time relative time to schedule job, in ms
+ */
+ void (*schedule_job_ms) (scheduler_t *this, job_t *job, u_int32_t ms);
+
+ /**
+ * Adds a event to the queue, using an absolut time.
+ *
+ * The passed timeval should be calculated based on the time_monotonic()
+ * function.
+ *
+ * @param job job to schedule
+ * @param time absolut time to schedule job
+ */
+ void (*schedule_job_tv) (scheduler_t *this, job_t *job, timeval_t tv);
+
+ /**
+ * Returns number of jobs scheduled.
+ *
+ * @return number of scheduled jobs
+ */
+ u_int (*get_job_load) (scheduler_t *this);
+
+ /**
+ * Destroys a scheduler object.
+ */
+ void (*destroy) (scheduler_t *this);
+};
+
+/**
+ * Create a scheduler.
+ *
+ * @return scheduler_t object
+ */
+scheduler_t *scheduler_create(void);
+
+#endif /** SCHEDULER_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c
new file mode 100644
index 000000000..13586a23e
--- /dev/null
+++ b/src/libcharon/sa/authenticators/authenticator.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2006-2009 Martin Willi
+ * 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 <string.h>
+
+#include "authenticator.h"
+
+#include <sa/authenticators/pubkey_authenticator.h>
+#include <sa/authenticators/psk_authenticator.h>
+#include <sa/authenticators/eap_authenticator.h>
+#include <encoding/payloads/auth_payload.h>
+
+
+ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS,
+ "RSA signature",
+ "pre-shared key",
+ "DSS signature");
+ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
+ "ECDSA-256 signature",
+ "ECDSA-384 signature",
+ "ECDSA-521 signature");
+ENUM_END(auth_method_names, AUTH_ECDSA_521);
+
+ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
+ "any",
+ "public key",
+ "pre-shared key",
+ "EAP",
+);
+
+/**
+ * Described in header.
+ */
+authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init)
+{
+ switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS))
+ {
+ case AUTH_CLASS_ANY:
+ /* defaults to PUBKEY */
+ case AUTH_CLASS_PUBKEY:
+ return (authenticator_t*)pubkey_authenticator_create_builder(ike_sa,
+ received_nonce, sent_init);
+ case AUTH_CLASS_PSK:
+ return (authenticator_t*)psk_authenticator_create_builder(ike_sa,
+ received_nonce, sent_init);
+ case AUTH_CLASS_EAP:
+ return (authenticator_t*)eap_authenticator_create_builder(ike_sa,
+ received_nonce, sent_nonce, received_init, sent_init);
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Described in header.
+ */
+authenticator_t *authenticator_create_verifier(
+ ike_sa_t *ike_sa, message_t *message,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init)
+{
+ auth_payload_t *auth_payload;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (auth_payload == NULL)
+ {
+ return (authenticator_t*)eap_authenticator_create_verifier(ike_sa,
+ received_nonce, sent_nonce, received_init, sent_init);
+ }
+ switch (auth_payload->get_auth_method(auth_payload))
+ {
+ case AUTH_RSA:
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ return (authenticator_t*)pubkey_authenticator_create_verifier(ike_sa,
+ sent_nonce, received_init);
+ case AUTH_PSK:
+ return (authenticator_t*)psk_authenticator_create_verifier(ike_sa,
+ sent_nonce, received_init);
+ default:
+ return NULL;
+ }
+}
+
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h
new file mode 100644
index 000000000..fff91ed34
--- /dev/null
+++ b/src/libcharon/sa/authenticators/authenticator.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup authenticator authenticator
+ * @{ @ingroup authenticators
+ */
+
+#ifndef AUTHENTICATOR_H_
+#define AUTHENTICATOR_H_
+
+typedef enum auth_method_t auth_method_t;
+typedef enum auth_class_t auth_class_t;
+typedef struct authenticator_t authenticator_t;
+
+#include <library.h>
+#include <config/auth_cfg.h>
+#include <sa/ike_sa.h>
+
+/**
+ * Method to use for authentication, as defined in IKEv2.
+ */
+enum auth_method_t {
+ /**
+ * Computed as specified in section 2.15 of RFC using
+ * an RSA private key over a PKCS#1 padded hash.
+ */
+ AUTH_RSA = 1,
+
+ /**
+ * Computed as specified in section 2.15 of RFC using the
+ * shared key associated with the identity in the ID payload
+ * and the negotiated prf function
+ */
+ AUTH_PSK = 2,
+
+ /**
+ * Computed as specified in section 2.15 of RFC using a
+ * DSS private key over a SHA-1 hash.
+ */
+ AUTH_DSS = 3,
+
+ /**
+ * ECDSA with SHA-256 on the P-256 curve as specified in RFC 4754
+ */
+ AUTH_ECDSA_256 = 9,
+
+ /**
+ * ECDSA with SHA-384 on the P-384 curve as specified in RFC 4754
+ */
+ AUTH_ECDSA_384 = 10,
+
+ /**
+ * ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754
+ */
+ AUTH_ECDSA_521 = 11,
+};
+
+/**
+ * enum names for auth_method_t.
+ */
+extern enum_name_t *auth_method_names;
+
+/**
+ * Class of authentication to use. This is different to auth_method_t in that
+ * it does not specify a method, but a class of acceptable methods. The found
+ * certificate finally dictates wich method is used.
+ */
+enum auth_class_t {
+ /** any class acceptable */
+ AUTH_CLASS_ANY = 0,
+ /** authentication using public keys (RSA, ECDSA) */
+ AUTH_CLASS_PUBKEY = 1,
+ /** authentication using a pre-shared secrets */
+ AUTH_CLASS_PSK = 2,
+ /** authentication using EAP */
+ AUTH_CLASS_EAP = 3,
+};
+
+/**
+ * enum strings for auth_class_t
+ */
+extern enum_name_t *auth_class_names;
+
+/**
+ * Authenticator interface implemented by the various authenticators.
+ *
+ * An authenticator implementation handles AUTH and EAP payloads. Received
+ * messages are passed to the process() method, to send authentication data
+ * the message is passed to the build() method.
+ */
+struct authenticator_t {
+
+ /**
+ * Process an incoming message using the authenticator.
+ *
+ * @param message message containing authentication payloads
+ * @return
+ * - SUCCESS if authentication successful
+ * - FAILED if authentication failed
+ * - NEED_MORE if another exchange required
+ */
+ status_t (*process)(authenticator_t *this, message_t *message);
+
+ /**
+ * Attach authentication data to an outgoing message.
+ *
+ * @param message message to add authentication data to
+ * @return
+ * - SUCCESS if authentication successful
+ * - FAILED if authentication failed
+ * - NEED_MORE if another exchange required
+ */
+ status_t (*build)(authenticator_t *this, message_t *message);
+
+ /**
+ * Check if the authenticator is capable of mutual authentication.
+ *
+ * Some authenticator authenticate both peers, e.g. EAP. To support
+ * mutual authentication with only a single authenticator (EAP-only
+ * authentication), it must be mutual. This method is invoked in ike_auth
+ * to check if the given authenticator is capable of doing so.
+ */
+ bool (*is_mutual)(authenticator_t *this);
+
+ /**
+ * Destroy authenticator instance.
+ */
+ void (*destroy) (authenticator_t *this);
+};
+
+/**
+ * Create an authenticator to build signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param cfg authentication configuration
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return authenticator, NULL if not supported
+ */
+authenticator_t *authenticator_create_builder(
+ ike_sa_t *ike_sa, auth_cfg_t *cfg,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init);
+
+/**
+ * Create an authenticator to verify signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param message message containing authentication data
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return authenticator, NULL if not supported
+ */
+authenticator_t *authenticator_create_verifier(
+ ike_sa_t *ike_sa, message_t *message,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init);
+
+#endif /** AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/eap_manager.c b/src/libcharon/sa/authenticators/eap/eap_manager.c
new file mode 100644
index 000000000..f795183f0
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/eap_manager.c
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#include "eap_manager.h"
+
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_eap_manager_t private_eap_manager_t;
+typedef struct eap_entry_t eap_entry_t;
+
+/**
+ * EAP constructor entry
+ */
+struct eap_entry_t {
+
+ /**
+ * EAP method type, vendor specific if vendor is set
+ */
+ eap_type_t type;
+
+ /**
+ * vendor ID, 0 for default EAP methods
+ */
+ u_int32_t vendor;
+
+ /**
+ * Role of the method returned by the constructor, EAP_SERVER or EAP_PEER
+ */
+ eap_role_t role;
+
+ /**
+ * constructor function to create instance
+ */
+ eap_constructor_t constructor;
+};
+
+/**
+ * private data of eap_manager
+ */
+struct private_eap_manager_t {
+
+ /**
+ * public functions
+ */
+ eap_manager_t public;
+
+ /**
+ * list of eap_entry_t's
+ */
+ linked_list_t *methods;
+
+ /**
+ * rwlock to lock methods
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Implementation of eap_manager_t.add_method.
+ */
+static void add_method(private_eap_manager_t *this, eap_type_t type,
+ u_int32_t vendor, eap_role_t role,
+ eap_constructor_t constructor)
+{
+ eap_entry_t *entry = malloc_thing(eap_entry_t);
+
+ entry->type = type;
+ entry->vendor = vendor;
+ entry->role = role;
+ entry->constructor = constructor;
+
+ this->lock->write_lock(this->lock);
+ this->methods->insert_last(this->methods, entry);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of eap_manager_t.remove_method.
+ */
+static void remove_method(private_eap_manager_t *this, eap_constructor_t constructor)
+{
+ enumerator_t *enumerator;
+ eap_entry_t *entry;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->methods->create_enumerator(this->methods);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (constructor == entry->constructor)
+ {
+ this->methods->remove_at(this->methods, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of eap_manager_t.create_instance.
+ */
+static eap_method_t* create_instance(private_eap_manager_t *this,
+ eap_type_t type, u_int32_t vendor,
+ eap_role_t role, identification_t *server,
+ identification_t *peer)
+{
+ enumerator_t *enumerator;
+ eap_entry_t *entry;
+ eap_method_t *method = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->methods->create_enumerator(this->methods);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (type == entry->type && vendor == entry->vendor &&
+ role == entry->role)
+ {
+ method = entry->constructor(server, peer);
+ if (method)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return method;
+}
+
+/**
+ * Implementation of 2008_t.destroy
+ */
+static void destroy(private_eap_manager_t *this)
+{
+ this->methods->destroy_function(this->methods, free);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+eap_manager_t *eap_manager_create()
+{
+ private_eap_manager_t *this = malloc_thing(private_eap_manager_t);
+
+ this->public.add_method = (void(*)(eap_manager_t*, eap_type_t type, u_int32_t vendor, eap_role_t role, eap_constructor_t constructor))add_method;
+ this->public.remove_method = (void(*)(eap_manager_t*, eap_constructor_t constructor))remove_method;
+ this->public.create_instance = (eap_method_t*(*)(eap_manager_t*, eap_type_t type, u_int32_t vendor, eap_role_t role, identification_t*,identification_t*))create_instance;
+ this->public.destroy = (void(*)(eap_manager_t*))destroy;
+
+ this->methods = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/authenticators/eap/eap_manager.h b/src/libcharon/sa/authenticators/eap/eap_manager.h
new file mode 100644
index 000000000..0333fb6da
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/eap_manager.h
@@ -0,0 +1,82 @@
+/*
+ * 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 eap_manager eap_manager
+ * @{ @ingroup eap
+ */
+
+#ifndef EAP_MANAGER_H_
+#define EAP_MANAGER_H_
+
+#include <sa/authenticators/eap/eap_method.h>
+
+typedef struct eap_manager_t eap_manager_t;
+
+/**
+ * The EAP manager manages all EAP implementations and creates instances.
+ *
+ * A plugin registers it's implemented EAP method at the manager by
+ * providing type and a contructor function. The manager then instanciates
+ * eap_method_t instances through the provided constructor to handle
+ * EAP authentication.
+ */
+struct eap_manager_t {
+
+ /**
+ * Register a EAP method implementation.
+ *
+ * @param method vendor specific method, if vendor != 0
+ * @param vendor vendor ID, 0 for non-vendor (default) EAP methods
+ * @param role EAP role of the registered method
+ * @param constructor constructor function, returns an eap_method_t
+ */
+ void (*add_method)(eap_manager_t *this, eap_type_t type, u_int32_t vendor,
+ eap_role_t role, eap_constructor_t constructor);
+
+ /**
+ * Unregister a EAP method implementation using it's constructor.
+ *
+ * @param constructor constructor function to remove, as added in add_method
+ */
+ void (*remove_method)(eap_manager_t *this, eap_constructor_t constructor);
+
+ /**
+ * Create a new EAP method instance.
+ *
+ * @param type type of the EAP method
+ * @param vendor vendor ID, 0 for non-vendor (default) EAP methods
+ * @param role role of EAP method, either EAP_SERVER or EAP_PEER
+ * @param server identity of the server
+ * @param peer identity of the peer (client)
+ * @return EAP method instance, NULL if no constructor found
+ */
+ eap_method_t* (*create_instance)(eap_manager_t *this, eap_type_t type,
+ u_int32_t vendor, eap_role_t role,
+ identification_t *server,
+ identification_t *peer);
+
+ /**
+ * Destroy a eap_manager instance.
+ */
+ void (*destroy)(eap_manager_t *this);
+};
+
+/**
+ * Create a eap_manager instance.
+ */
+eap_manager_t *eap_manager_create();
+
+#endif /** EAP_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c
new file mode 100644
index 000000000..91fa5305f
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/eap_method.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2006 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 "eap_method.h"
+
+ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
+ "EAP_IDENTITY",
+ "EAP_NOTIFICATION",
+ "EAP_NAK",
+ "EAP_MD5",
+ "EAP_OTP",
+ "EAP_GTC");
+ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC,
+ "EAP_SIM");
+ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
+ "EAP_AKA");
+ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
+ "EAP_MSCHAPV2");
+ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
+ "EAP_RADIUS",
+ "EAP_EXPANDED",
+ "EAP_EXPERIMENTAL");
+ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
+
+ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
+ "ID",
+ "NTF",
+ "NAK",
+ "MD5",
+ "OTP",
+ "GTC");
+ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_GTC,
+ "SIM");
+ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM,
+ "AKA");
+ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
+ "MSCHAPV2");
+ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
+ "RAD",
+ "EXP",
+ "XP");
+ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
+
+/*
+ * See header
+ */
+eap_type_t eap_type_from_string(char *name)
+{
+ int i;
+ static struct {
+ char *name;
+ eap_type_t type;
+ } types[] = {
+ {"identity", EAP_IDENTITY},
+ {"md5", EAP_MD5},
+ {"otp", EAP_OTP},
+ {"gtc", EAP_GTC},
+ {"sim", EAP_SIM},
+ {"aka", EAP_AKA},
+ {"mschapv2", EAP_MSCHAPV2},
+ {"radius", EAP_RADIUS},
+ };
+
+ for (i = 0; i < countof(types); i++)
+ {
+ if (strcaseeq(name, types[i].name))
+ {
+ return types[i].type;
+ }
+ }
+ return 0;
+}
+
+ENUM(eap_code_names, EAP_REQUEST, EAP_FAILURE,
+ "EAP_REQUEST",
+ "EAP_RESPONSE",
+ "EAP_SUCCESS",
+ "EAP_FAILURE",
+);
+
+ENUM(eap_code_short_names, EAP_REQUEST, EAP_FAILURE,
+ "REQ",
+ "RES",
+ "SUCC",
+ "FAIL",
+);
+
+ENUM(eap_role_names, EAP_SERVER, EAP_PEER,
+ "EAP_SERVER",
+ "EAP_PEER",
+);
+
+
+
+
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h
new file mode 100644
index 000000000..4cab84535
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/eap_method.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2006 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 eap_method eap_method
+ * @{ @ingroup eap
+ */
+
+#ifndef EAP_METHOD_H_
+#define EAP_METHOD_H_
+
+typedef struct eap_method_t eap_method_t;
+typedef enum eap_role_t eap_role_t;
+typedef enum eap_type_t eap_type_t;
+typedef enum eap_code_t eap_code_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <encoding/payloads/eap_payload.h>
+
+/**
+ * Role of an eap_method, SERVER or PEER (client)
+ */
+enum eap_role_t {
+ EAP_SERVER,
+ EAP_PEER,
+};
+/**
+ * enum names for eap_role_t.
+ */
+extern enum_name_t *eap_role_names;
+
+/**
+ * EAP types, defines the EAP method implementation
+ */
+enum eap_type_t {
+ EAP_IDENTITY = 1,
+ EAP_NOTIFICATION = 2,
+ EAP_NAK = 3,
+ EAP_MD5 = 4,
+ EAP_OTP = 5,
+ EAP_GTC = 6,
+ EAP_SIM = 18,
+ EAP_AKA = 23,
+ EAP_MSCHAPV2 = 26,
+ /** not a method, but an implementation providing different methods */
+ EAP_RADIUS = 253,
+ EAP_EXPANDED = 254,
+ EAP_EXPERIMENTAL = 255,
+};
+
+/**
+ * enum names for eap_type_t.
+ */
+extern enum_name_t *eap_type_names;
+
+/**
+ * short string enum names for eap_type_t.
+ */
+extern enum_name_t *eap_type_short_names;
+
+/**
+ * Lookup the EAP method type from a string.
+ *
+ * @param name EAP method name (such as "md5", "aka")
+ * @return method type, 0 if unkown
+ */
+eap_type_t eap_type_from_string(char *name);
+
+/**
+ * EAP code, type of an EAP message
+ */
+enum eap_code_t {
+ EAP_REQUEST = 1,
+ EAP_RESPONSE = 2,
+ EAP_SUCCESS = 3,
+ EAP_FAILURE = 4,
+};
+
+/**
+ * enum names for eap_code_t.
+ */
+extern enum_name_t *eap_code_names;
+
+/**
+ * short string enum names for eap_code_t.
+ */
+extern enum_name_t *eap_code_short_names;
+
+/**
+ * Interface of an EAP method for server and client side.
+ *
+ * An EAP method initiates an EAP exchange and processes requests and
+ * responses. An EAP method may need multiple exchanges before succeeding, and
+ * the eap_authentication may use multiple EAP methods to authenticate a peer.
+ * To accomplish these requirements, all EAP methods have their own
+ * implementation while the eap_authenticatior uses one or more of these
+ * EAP methods. Sending of EAP(SUCCESS/FAILURE) message is not the job
+ * of the method, the eap_authenticator does this.
+ * An EAP method may establish a MSK, this is used the complete the
+ * authentication. Even if a mutual EAP method is used, the traditional
+ * AUTH payloads are required. Only these include the nonces and messages from
+ * ike_sa_init and therefore prevent man in the middle attacks.
+ * The EAP method must use an initial EAP identifier value != 0, as a preceding
+ * EAP-Identity exchange always uses identifier 0.
+ */
+struct eap_method_t {
+
+ /**
+ * Initiate the EAP exchange.
+ *
+ * initiate() is only useable for server implementations, as clients only
+ * reply to server requests.
+ * A eap_payload is created in "out" if result is NEED_MORE.
+ *
+ * @param out eap_payload to send to the client
+ * @return
+ * - NEED_MORE, if an other exchange is required
+ * - FAILED, if unable to create eap request payload
+ */
+ status_t (*initiate) (eap_method_t *this, eap_payload_t **out);
+
+ /**
+ * Process a received EAP message.
+ *
+ * A eap_payload is created in "out" if result is NEED_MORE.
+ *
+ * @param in eap_payload response received
+ * @param out created eap_payload to send
+ * @return
+ * - NEED_MORE, if an other exchange is required
+ * - FAILED, if EAP method failed
+ * - SUCCESS, if EAP method succeeded
+ */
+ status_t (*process) (eap_method_t *this, eap_payload_t *in,
+ eap_payload_t **out);
+
+ /**
+ * Get the EAP type implemented in this method.
+ *
+ * @param vendor pointer receiving vendor identifier for type, 0 for none
+ * @return type of the EAP method
+ */
+ eap_type_t (*get_type) (eap_method_t *this, u_int32_t *vendor);
+
+ /**
+ * Check if this EAP method authenticates the server.
+ *
+ * Some EAP methods provide mutual authentication and
+ * allow authentication using only EAP, if the peer supports it.
+ *
+ * @return TRUE if methods provides mutual authentication
+ */
+ bool (*is_mutual) (eap_method_t *this);
+
+ /**
+ * Get the MSK established by this EAP method.
+ *
+ * Not all EAP methods establish a shared secret. For implementations of
+ * the EAP-Identity method, get_msk() returns the received identity.
+ *
+ * @param msk chunk receiving internal stored MSK
+ * @return
+ * - SUCCESS, or
+ * - FAILED, if MSK not established (yet)
+ */
+ status_t (*get_msk) (eap_method_t *this, chunk_t *msk);
+
+ /**
+ * Destroys a eap_method_t object.
+ */
+ void (*destroy) (eap_method_t *this);
+};
+
+/**
+ * Constructor definition for a pluggable EAP method.
+ *
+ * Each EAP module must define a constructor function which will return
+ * an initialized object with the methods defined in eap_method_t.
+ * Constructors for server and peers are identical, to support both roles
+ * of a EAP method, a plugin needs register two constructors in the
+ * eap_manager_t.
+ * The passed identites are of type ID_EAP and valid only during the
+ * constructor invocation.
+ *
+ * @param server ID of the server to use for credential lookup
+ * @param peer ID of the peer to use for credential lookup
+ * @return implementation of the eap_method_t interface
+ */
+typedef eap_method_t *(*eap_constructor_t)(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_METHOD_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.c b/src/libcharon/sa/authenticators/eap/sim_manager.c
new file mode 100644
index 000000000..157865083
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/sim_manager.c
@@ -0,0 +1,534 @@
+/*
+ * 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.
+ */
+
+#include "sim_manager.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+
+typedef struct private_sim_manager_t private_sim_manager_t;
+
+/**
+ * Private data of an sim_manager_t object.
+ */
+struct private_sim_manager_t {
+
+ /**
+ * Public sim_manager_t interface.
+ */
+ sim_manager_t public;
+
+ /**
+ * list of added cards
+ */
+ linked_list_t *cards;
+
+ /**
+ * list of added provider
+ */
+ linked_list_t *providers;
+
+ /**
+ * list of added hooks
+ */
+ linked_list_t *hooks;
+};
+
+/**
+ * Implementation of sim_manager_t.add_card
+ */
+static void add_card(private_sim_manager_t *this, sim_card_t *card)
+{
+ this->cards->insert_last(this->cards, card);
+}
+
+/**
+ * Implementation of sim_manager_t.remove_card
+ */
+static void remove_card(private_sim_manager_t *this, sim_card_t *card)
+{
+ this->cards->remove(this->cards, card, NULL);
+}
+
+/**
+ * Implementation of sim_manager_t.card_get_triplet
+ */
+static bool card_get_triplet(private_sim_manager_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
+ char kc[SIM_KC_LEN])
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+ int tried = 0;
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ if (card->get_triplet(card, id, rand, sres, kc))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ tried++;
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'",
+ tried, id);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_manager_t.card_get_quintuplet
+ */
+static status_t card_get_quintuplet(private_sim_manager_t *this,
+ identification_t *id, char rand[AKA_RAND_LEN],
+ char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
+ char ik[AKA_IK_LEN], char res[AKA_RES_MAX],
+ int *res_len)
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+ status_t status = NOT_FOUND;
+ int tried = 0;
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ status = card->get_quintuplet(card, id, rand, autn, ck, ik, res, res_len);
+ switch (status)
+ { /* try next on error, but not on INVALID_STATE */
+ case SUCCESS:
+ case INVALID_STATE:
+ enumerator->destroy(enumerator);
+ return status;
+ case NOT_SUPPORTED:
+ case FAILED:
+ default:
+ tried++;
+ continue;
+ }
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'",
+ tried, id);
+ return status;
+}
+
+/**
+ * Implementation of sim_manager_t.card_resync
+ */
+static bool card_resync(private_sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ if (card->resync(card, id, rand, auts))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_manager_t.card_set_pseudonym
+ */
+static void card_set_pseudonym(private_sim_manager_t *this,
+ identification_t *id, identification_t *pseudonym)
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+
+ DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id);
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ card->set_pseudonym(card, id, pseudonym);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of sim_manager_t.card_get_pseudonym
+ */
+static identification_t* card_get_pseudonym(private_sim_manager_t *this,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+ identification_t *pseudonym = NULL;
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ pseudonym = card->get_pseudonym(card, id);
+ if (pseudonym)
+ {
+ DBG1(DBG_IKE, "using stored pseudonym identity '%Y' "
+ "instead of '%Y'", pseudonym, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return pseudonym;
+}
+
+/**
+ * Implementation of sim_manager_t.card_set_reauth
+ */
+static void card_set_reauth(private_sim_manager_t *this, identification_t *id,
+ identification_t *next, char mk[HASH_SIZE_SHA1],
+ u_int16_t counter)
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+
+ DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'",
+ next, id);
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ card->set_reauth(card, id, next, mk, counter);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of sim_manager_t.card_get_reauth
+ */
+static identification_t* card_get_reauth(private_sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter)
+{
+ enumerator_t *enumerator;
+ sim_card_t *card;
+ identification_t *reauth = NULL;
+
+ enumerator = this->cards->create_enumerator(this->cards);
+ while (enumerator->enumerate(enumerator, &card))
+ {
+ reauth = card->get_reauth(card, id, mk, counter);
+ if (reauth)
+ {
+ DBG1(DBG_IKE, "using stored reauthentication identity '%Y' "
+ "instead of '%Y'", reauth, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return reauth;
+}
+
+/**
+ * Implementation of sim_manager_t.add_provider
+ */
+static void add_provider(private_sim_manager_t *this, sim_provider_t *provider)
+{
+ this->providers->insert_last(this->providers, provider);
+}
+
+/**
+ * Implementation of sim_manager_t.remove_provider
+ */
+static void remove_provider(private_sim_manager_t *this,
+ sim_provider_t *provider)
+{
+ this->providers->remove(this->providers, provider, NULL);
+}
+
+/**
+ * Implementation of sim_manager_t.provider_get_triplet
+ */
+static bool provider_get_triplet(private_sim_manager_t *this,
+ identification_t *id, char rand[SIM_RAND_LEN],
+ char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ int tried = 0;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ if (provider->get_triplet(provider, id, rand, sres, kc))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ tried++;
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'",
+ tried, id);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_get_quintuplet
+ */
+static bool provider_get_quintuplet(private_sim_manager_t *this,
+ identification_t *id, char rand[AKA_RAND_LEN],
+ char xres[AKA_RES_MAX], int *xres_len,
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char autn[AKA_AUTN_LEN])
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ int tried = 0;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ if (provider->get_quintuplet(provider, id, rand, xres, xres_len,
+ ck, ik, autn))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'",
+ tried, id);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_resync
+ */
+static bool provider_resync(private_sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ if (provider->resync(provider, id, rand, auts))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_is_pseudonym
+ */
+static identification_t* provider_is_pseudonym(private_sim_manager_t *this,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ identification_t *permanent = NULL;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ permanent = provider->is_pseudonym(provider, id);
+ if (permanent)
+ {
+ DBG1(DBG_IKE, "received pseudonym identity '%Y' "
+ "mapping to '%Y'", id, permanent);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return permanent;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_gen_pseudonym
+ */
+static identification_t* provider_gen_pseudonym(private_sim_manager_t *this,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ identification_t *pseudonym = NULL;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ pseudonym = provider->gen_pseudonym(provider, id);
+ if (pseudonym)
+ {
+ DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return pseudonym;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_is_reauth
+ */
+static identification_t* provider_is_reauth(private_sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter)
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ identification_t *permanent = NULL;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ permanent = provider->is_reauth(provider, id, mk, counter);
+ if (permanent)
+ {
+ DBG1(DBG_IKE, "received reauthentication identity '%Y' "
+ "mapping to '%Y'", id, permanent);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return permanent;
+}
+
+/**
+ * Implementation of sim_manager_t.provider_gen_reauth
+ */
+static identification_t* provider_gen_reauth(private_sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1])
+{
+ enumerator_t *enumerator;
+ sim_provider_t *provider;
+ identification_t *reauth = NULL;
+
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &provider))
+ {
+ reauth = provider->gen_reauth(provider, id, mk);
+ if (reauth)
+ {
+ DBG1(DBG_IKE, "proposing new reauthentication identity '%Y'", reauth);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return reauth;
+}
+
+/**
+ * Implementation of sim_manager_t.add_hooks
+ */
+static void add_hooks(private_sim_manager_t *this, sim_hooks_t *hooks)
+{
+ this->hooks->insert_last(this->hooks, hooks);
+}
+
+/**
+ * Implementation of sim_manager_t.remove_hooks
+ */
+static void remove_hooks(private_sim_manager_t *this, sim_hooks_t *hooks)
+{
+ this->hooks->remove(this->hooks, hooks, NULL);
+}
+
+/**
+ * Implementation of sim_manager_t.message_hook
+ */
+static void message_hook(private_sim_manager_t *this,
+ simaka_message_t *message, bool inbound, bool decrypted)
+{
+ enumerator_t *enumerator;
+ sim_hooks_t *hooks;
+
+ enumerator = this->hooks->create_enumerator(this->hooks);
+ while (enumerator->enumerate(enumerator, &hooks))
+ {
+ hooks->message(hooks, message, inbound, decrypted);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of sim_manager_t.key_hook
+ */
+static void key_hook(private_sim_manager_t *this,
+ chunk_t k_encr, chunk_t k_auth)
+{
+ enumerator_t *enumerator;
+ sim_hooks_t *hooks;
+
+ enumerator = this->hooks->create_enumerator(this->hooks);
+ while (enumerator->enumerate(enumerator, &hooks))
+ {
+ hooks->keys(hooks, k_encr, k_auth);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of sim_manager_t.destroy.
+ */
+static void destroy(private_sim_manager_t *this)
+{
+ this->cards->destroy(this->cards);
+ this->providers->destroy(this->providers);
+ this->hooks->destroy(this->hooks);
+ free(this);
+}
+
+/**
+ * See header
+ */
+sim_manager_t *sim_manager_create()
+{
+ private_sim_manager_t *this = malloc_thing(private_sim_manager_t);
+
+ this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card;
+ this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card;
+ this->public.card_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))card_get_triplet;
+ this->public.card_get_quintuplet = (status_t(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))card_get_quintuplet;
+ this->public.card_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))card_resync;
+ this->public.card_set_pseudonym = (void(*)(sim_manager_t*, identification_t *id, identification_t *pseudonym))card_set_pseudonym;
+ this->public.card_get_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))card_get_pseudonym;
+ this->public.card_set_reauth = (void(*)(sim_manager_t*, identification_t *id, identification_t *next, char mk[HASH_SIZE_SHA1], u_int16_t counter))card_set_reauth;
+ this->public.card_get_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))card_get_reauth;
+ this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider;
+ this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider;
+ this->public.provider_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))provider_get_triplet;
+ this->public.provider_get_quintuplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))provider_get_quintuplet;
+ this->public.provider_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))provider_resync;
+ this->public.provider_is_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_is_pseudonym;
+ this->public.provider_gen_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_gen_pseudonym;
+ this->public.provider_is_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))provider_is_reauth;
+ this->public.provider_gen_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))provider_gen_reauth;
+ this->public.add_hooks = (void(*)(sim_manager_t*, sim_hooks_t *hooks))add_hooks;
+ this->public.remove_hooks = (void(*)(sim_manager_t*, sim_hooks_t *hooks))remove_hooks;
+ this->public.message_hook = (void(*)(sim_manager_t*, simaka_message_t *message, bool inbound, bool decrypted))message_hook;
+ this->public.key_hook = (void(*)(sim_manager_t*, chunk_t k_encr, chunk_t k_auth))key_hook;
+ this->public.destroy = (void(*)(sim_manager_t*))destroy;
+
+ this->cards = linked_list_create();
+ this->providers = linked_list_create();
+ this->hooks = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.h b/src/libcharon/sa/authenticators/eap/sim_manager.h
new file mode 100644
index 000000000..9aa661ac8
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap/sim_manager.h
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2008-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 sim_manager sim_manager
+ * @{ @ingroup eap
+ */
+
+#ifndef SIM_MANAGER_H_
+#define SIM_MANAGER_H_
+
+#include <crypto/hashers/hasher.h>
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+#include <sa/authenticators/eap/eap_method.h>
+
+typedef struct sim_manager_t sim_manager_t;
+typedef struct sim_card_t sim_card_t;
+typedef struct sim_provider_t sim_provider_t;
+typedef struct sim_hooks_t sim_hooks_t;
+
+/** implemented in libsimaka, but we need it for the message hook */
+typedef struct simaka_message_t simaka_message_t;
+
+#define SIM_RAND_LEN 16
+#define SIM_SRES_LEN 4
+#define SIM_KC_LEN 8
+
+#define AKA_RAND_LEN 16
+#define AKA_RES_MAX 16
+#define AKA_CK_LEN 16
+#define AKA_IK_LEN 16
+#define AKA_AUTN_LEN 16
+#define AKA_AUTS_LEN 14
+
+/**
+ * Interface for a (U)SIM card (used as EAP client).
+ *
+ * The SIM card completes triplets/quintuplets requested in a challenge
+ * received from the server.
+ * An implementation supporting only one of SIM/AKA authentication may
+ * implement the other methods with return_false()/return NOT_SUPPORTED/NULL.
+ */
+struct sim_card_t {
+
+ /**
+ * Calculate SRES/KC from a RAND for SIM authentication.
+ *
+ * @param id permanent identity to get a triplet for
+ * @param rand RAND input buffer, fixed size 16 bytes
+ * @param sres SRES output buffer, fixed size 4 byte
+ * @param kc KC output buffer, fixed size 8 bytes
+ * @return TRUE if SRES/KC calculated, FALSE on error/wrong identity
+ */
+ bool (*get_triplet)(sim_card_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
+ char kc[SIM_KC_LEN]);
+
+ /**
+ * Calculate CK/IK/RES from RAND/AUTN for AKA authentication.
+ *
+ * If the received sequence number (in autn) is out of sync, INVALID_STATE
+ * is returned.
+ * The RES value is the only one with variable length. Pass a buffer
+ * of at least AKA_RES_MAX, the actual number of bytes is written to the
+ * res_len value. While the standard would allow any bit length between
+ * 32 and 128 bits, we support only full bytes for now.
+ *
+ * @param id permanent identity to request quintuplet for
+ * @param rand random value rand
+ * @param autn authentication token autn
+ * @param ck buffer receiving encryption key ck
+ * @param ik buffer receiving integrity key ik
+ * @param res buffer receiving authentication result res
+ * @param res_len nubmer of bytes written to res buffer
+ * @return SUCCESS, FAILED, or INVALID_STATE if out of sync
+ */
+ status_t (*get_quintuplet)(sim_card_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN],
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char res[AKA_RES_MAX], int *res_len);
+
+ /**
+ * Calculate AUTS from RAND for AKA resynchronization.
+ *
+ * @param id permanent identity to request quintuplet for
+ * @param rand random value rand
+ * @param auts resynchronization parameter auts
+ * @return TRUE if parameter generated successfully
+ */
+ bool (*resync)(sim_card_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
+
+ /**
+ * Set the pseudonym to use for next authentication.
+ *
+ * @param id permanent identity of the peer
+ * @param pseudonym pseudonym identity received from the server
+ */
+ void (*set_pseudonym)(sim_card_t *this, identification_t *id,
+ identification_t *pseudonym);
+
+ /**
+ * Get the pseudonym previously stored via set_pseudonym().
+ *
+ * @param id permanent identity of the peer
+ * @return associated pseudonym identity, NULL if none stored
+ */
+ identification_t* (*get_pseudonym)(sim_card_t *this, identification_t *id);
+
+ /**
+ * Store parameters to use for the next fast reauthentication.
+ *
+ * @param id permanent identity of the peer
+ * @param next next fast reauthentication identity to use
+ * @param mk master key MK to store for reauthentication
+ * @param counter counter value to store, host order
+ */
+ void (*set_reauth)(sim_card_t *this, identification_t *id,
+ identification_t *next, char mk[HASH_SIZE_SHA1],
+ u_int16_t counter);
+
+ /**
+ * Retrieve parameters for fast reauthentication stored via set_reauth().
+ *
+ * @param id permanent identity of the peer
+ * @param mk buffer receiving master key MK
+ * @param counter pointer receiving counter value, in host order
+ * @return fast reauthentication identity, NULL if not found
+ */
+ identification_t* (*get_reauth)(sim_card_t *this, identification_t *id,
+ char mk[HASH_SIZE_SHA1], u_int16_t *counter);
+};
+
+/**
+ * Interface for a triplet/quintuplet provider (used as EAP server).
+ *
+ * A SIM provider hands out triplets for SIM authentication and quintuplets
+ * for AKA authentication. Multiple SIM provider instances can serve as
+ * authentication backend to authenticate clients using SIM/AKA.
+ * An implementation supporting only one of SIM/AKA authentication may
+ * implement the other methods with return_false().
+ */
+struct sim_provider_t {
+
+ /**
+ * Create a challenge for SIM authentication.
+ *
+ * @param id permanent identity of peer to gen triplet for
+ * @param rand RAND output buffer, fixed size 16 bytes
+ * @param sres SRES output buffer, fixed size 4 byte
+ * @param kc KC output buffer, fixed size 8 bytes
+ * @return TRUE if triplet received, FALSE otherwise
+ */
+ bool (*get_triplet)(sim_provider_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
+ char kc[SIM_KC_LEN]);
+
+ /**
+ * Create a challenge for AKA authentication.
+ *
+ * The XRES value is the only one with variable length. Pass a buffer
+ * of at least AKA_RES_MAX, the actual number of bytes is written to the
+ * xres_len value. While the standard would allow any bit length between
+ * 32 and 128 bits, we support only full bytes for now.
+ *
+ * @param id permanent identity of peer to create challenge for
+ * @param rand buffer receiving random value rand
+ * @param xres buffer receiving expected authentication result xres
+ * @param xres_len nubmer of bytes written to xres buffer
+ * @param ck buffer receiving encryption key ck
+ * @param ik buffer receiving integrity key ik
+ * @param autn authentication token autn
+ * @return TRUE if quintuplet generated successfully
+ */
+ bool (*get_quintuplet)(sim_provider_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN],
+ char xres[AKA_RES_MAX], int *xres_len,
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char autn[AKA_AUTN_LEN]);
+
+ /**
+ * Process AKA resynchroniusation request of a peer.
+ *
+ * @param id permanent identity of peer requesting resynchronisation
+ * @param rand random value rand
+ * @param auts synchronization parameter auts
+ * @return TRUE if resynchronized successfully
+ */
+ bool (*resync)(sim_provider_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
+
+ /**
+ * Check if peer uses a pseudonym, get permanent identity.
+ *
+ * @param id pseudonym identity candidate
+ * @return permanent identity, NULL if id not a pseudonym
+ */
+ identification_t* (*is_pseudonym)(sim_provider_t *this,
+ identification_t *id);
+
+ /**
+ * Generate a pseudonym identitiy for a given peer identity.
+ *
+ * @param id permanent identity to generate a pseudonym for
+ * @return generated pseudonym, NULL to not use a pseudonym identity
+ */
+ identification_t* (*gen_pseudonym)(sim_provider_t *this,
+ identification_t *id);
+
+ /**
+ * Check if peer uses reauthentication, retrieve reauth parameters.
+ *
+ * @param id reauthentication identity (candidate)
+ * @param mk buffer receiving master key MK
+ * @param counter pointer receiving current counter value, host order
+ * @return permanent identity, NULL if id not a reauth identity
+ */
+ identification_t* (*is_reauth)(sim_provider_t *this, identification_t *id,
+ char mk[HASH_SIZE_SHA1], u_int16_t *counter);
+
+ /**
+ * Generate a fast reauthentication identity, associated to a master key.
+ *
+ * @param id permanent peer identity
+ * @param mk master key to store along with generated identity
+ * @return fast reauthentication identity, NULL to not use reauth
+ */
+ identification_t* (*gen_reauth)(sim_provider_t *this, identification_t *id,
+ char mk[HASH_SIZE_SHA1]);
+};
+
+/**
+ * Additional hooks invoked during EAP-SIM/AKA message processing.
+ */
+struct sim_hooks_t {
+
+ /**
+ * SIM/AKA message parsing.
+ *
+ * As a SIM/AKA optionally contains encrypted attributes, the hook
+ * might get invoked twice, once before and once after decryption.
+ *
+ * @param message SIM/AKA message
+ * @param inbound TRUE for incoming messages, FALSE for outgoing
+ * @param decrypted TRUE if AT_ENCR_DATA has been decrypted
+ */
+ void (*message)(sim_hooks_t *this, simaka_message_t *message,
+ bool inbound, bool decrypted);
+
+ /**
+ * SIM/AKA encryption/authentication key hooks.
+ *
+ * @param k_encr derived SIM/AKA encryption key k_encr
+ * @param k_auth derived SIM/AKA authentication key k_auth
+ */
+ void (*keys)(sim_hooks_t *this, chunk_t k_encr, chunk_t k_auth);
+};
+
+/**
+ * The SIM manager handles multiple (U)SIM cards/providers and hooks.
+ */
+struct sim_manager_t {
+
+ /**
+ * Register a SIM card (client) at the manager.
+ *
+ * @param card sim card to register
+ */
+ void (*add_card)(sim_manager_t *this, sim_card_t *card);
+
+ /**
+ * Unregister a previously registered card from the manager.
+ *
+ * @param card sim card to unregister
+ */
+ void (*remove_card)(sim_manager_t *this, sim_card_t *card);
+
+ /**
+ * Calculate SIM triplets on one of the registered SIM cards.
+ *
+ * @param id permanent identity to get a triplet for
+ * @param rand RAND input buffer, fixed size 16 bytes
+ * @param sres SRES output buffer, fixed size 4 byte
+ * @param kc KC output buffer, fixed size 8 bytes
+ * @return TRUE if calculated, FALSE if no matching card found
+ */
+ bool (*card_get_triplet)(sim_manager_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
+ char kc[SIM_KC_LEN]);
+
+ /**
+ * Calculate AKA quitpulets on one of the registered SIM cards.
+ *
+ * @param id permanent identity to request quintuplet for
+ * @param rand random value rand
+ * @param autn authentication token autn
+ * @param ck buffer receiving encryption key ck
+ * @param ik buffer receiving integrity key ik
+ * @param res buffer receiving authentication result res
+ * @param res_len nubmer of bytes written to res buffer
+ * @return SUCCESS, FAILED, or INVALID_STATE if out of sync
+ */
+ status_t (*card_get_quintuplet)(sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN],
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char res[AKA_RES_MAX], int *res_len);
+
+ /**
+ * Calculate resynchronization data on one of the registered SIM cards.
+ *
+ * @param id permanent identity to request quintuplet for
+ * @param rand random value rand
+ * @param auts resynchronization parameter auts
+ * @return TRUE if calculated, FALSE if no matcing card found
+ */
+ bool (*card_resync)(sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
+
+ /**
+ * Store a received pseudonym on one of the registered SIM cards.
+ *
+ * @param id permanent identity of the peer
+ * @param pseudonym pseudonym identity received from the server
+ */
+ void (*card_set_pseudonym)(sim_manager_t *this, identification_t *id,
+ identification_t *pseudonym);
+
+ /**
+ * Get a stored pseudonym from one of the registerd SIM cards.
+ *
+ * @param id permanent identity of the peer
+ * @return associated pseudonym identity, NULL if none found
+ */
+ identification_t* (*card_get_pseudonym)(sim_manager_t *this,
+ identification_t *id);
+
+ /**
+ * Store fast reauthentication parameters on one of the registered cards.
+ *
+ * @param id permanent identity of the peer
+ * @param next next fast reauthentication identity to use
+ * @param mk master key MK to store for reauthentication
+ * @param counter counter value to store, host order
+ */
+ void (*card_set_reauth)(sim_manager_t *this, identification_t *id,
+ identification_t *next, char mk[HASH_SIZE_SHA1],
+ u_int16_t counter);
+
+ /**
+ * Retrieve fast reauthentication parameters from one of the registerd cards.
+ *
+ * @param id permanent identity of the peer
+ * @param mk buffer receiving master key MK
+ * @param counter pointer receiving counter value, in host order
+ * @return fast reauthentication identity, NULL if none found
+ */
+ identification_t* (*card_get_reauth)(sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter);
+
+ /**
+ * Register a triplet provider (server) at the manager.
+ *
+ * @param card sim card to register
+ */
+ void (*add_provider)(sim_manager_t *this, sim_provider_t *provider);
+
+ /**
+ * Unregister a previously registered provider from the manager.
+ *
+ * @param card sim card to unregister
+ */
+ void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider);
+
+ /**
+ * Get a SIM triplet from one of the registered providers.
+ *
+ * @param id permanent identity of peer to gen triplet for
+ * @param rand RAND output buffer, fixed size 16 bytes
+ * @param sres SRES output buffer, fixed size 4 byte
+ * @param kc KC output buffer, fixed size 8 bytes
+ * @return TRUE if triplet received, FALSE if no match found
+ */
+ bool (*provider_get_triplet)(sim_manager_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
+ char kc[SIM_KC_LEN]);
+
+ /**
+ * Get a AKA quintuplet from one of the registered providers.
+ *
+ * @param id permanent identity of peer to create challenge for
+ * @param rand buffer receiving random value rand
+ * @param xres buffer receiving expected authentication result xres
+ * @param ck buffer receiving encryption key ck
+ * @param ik buffer receiving integrity key ik
+ * @param autn authentication token autn
+ * @return TRUE if quintuplet received, FALSE if no match found
+ */
+ bool (*provider_get_quintuplet)(sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN],
+ char xres[AKA_RES_MAX], int *xres_len,
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
+ char autn[AKA_AUTN_LEN]);
+
+ /**
+ * Pass AKA resynchronization data to one of the registered providers.
+ *
+ * @param id permanent identity of peer requesting resynchronisation
+ * @param rand random value rand
+ * @param auts synchronization parameter auts
+ * @return TRUE if resynchronized, FALSE if not handled
+ */
+ bool (*provider_resync)(sim_manager_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
+
+ /**
+ * Check if a peer uses a pseudonym using one of the registered providers.
+ *
+ * @param id pseudonym identity candidate
+ * @return permanent identity, NULL if id not a pseudonym
+ */
+ identification_t* (*provider_is_pseudonym)(sim_manager_t *this,
+ identification_t *id);
+
+ /**
+ * Generate a new pseudonym using one of the registered providers.
+ *
+ * @param id permanent identity to generate a pseudonym for
+ * @return generated pseudonym, NULL to not use a pseudonym identity
+ */
+ identification_t* (*provider_gen_pseudonym)(sim_manager_t *this,
+ identification_t *id);
+
+ /**
+ * Check if a peer uses a reauth id using one of the registered providers.
+ *
+ * @param id reauthentication identity (candidate)
+ * @param mk buffer receiving master key MK
+ * @param counter pointer receiving current counter value, host order
+ * @return permanent identity, NULL if not a known reauth identity
+ */
+ identification_t* (*provider_is_reauth)(sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1],
+ u_int16_t *counter);
+
+ /**
+ * Generate a fast reauth id using one of the registered providers.
+ *
+ * @param id permanent peer identity
+ * @param mk master key to store along with generated identity
+ * @return fast reauthentication identity, NULL to not use reauth
+ */
+ identification_t* (*provider_gen_reauth)(sim_manager_t *this,
+ identification_t *id, char mk[HASH_SIZE_SHA1]);
+
+ /**
+ * Register a set of hooks to the manager.
+ *
+ * @param hooks hook interface implementation to register
+ */
+ void (*add_hooks)(sim_manager_t *this, sim_hooks_t *hooks);
+
+ /**
+ * Unregister a set of hooks from the manager.
+ *
+ * @param hooks hook interface implementation to unregister
+ */
+ void (*remove_hooks)(sim_manager_t *this, sim_hooks_t *hooks);
+
+ /**
+ * Invoke SIM/AKA message hook.
+ *
+ * @param message SIM message
+ * @param inbound TRUE for incoming messages, FALSE for outgoing
+ * @param decrypted TRUE if AT_ENCR_DATA has been decrypted
+ */
+ void (*message_hook)(sim_manager_t *this, simaka_message_t *message,
+ bool inbound, bool decrypted);
+
+ /**
+ * Invoke SIM/AKA key hook.
+ *
+ * @param k_encr SIM/AKA encryption key k_encr
+ * @param k_auth SIM/AKA authentication key k_auth
+ */
+ void (*key_hook)(sim_manager_t *this, chunk_t k_encr, chunk_t k_auth);
+
+ /**
+ * Destroy a manager instance.
+ */
+ void (*destroy)(sim_manager_t *this);
+};
+
+/**
+ * Create an SIM manager to handle multiple (U)SIM cards/providers.
+ *
+ * @return sim_t object
+ */
+sim_manager_t *sim_manager_create();
+
+#endif /** SIM_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
new file mode 100644
index 000000000..4617c4d8d
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2006-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 "eap_authenticator.h"
+
+#include <daemon.h>
+#include <sa/authenticators/eap/eap_method.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/eap_payload.h>
+
+typedef struct private_eap_authenticator_t private_eap_authenticator_t;
+
+/**
+ * Private data of an eap_authenticator_t object.
+ */
+struct private_eap_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_authenticator_t public;
+
+ /**
+ * Assigned IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * others nonce to include in AUTH calculation
+ */
+ chunk_t received_nonce;
+
+ /**
+ * our nonce to include in AUTH calculation
+ */
+ chunk_t sent_nonce;
+
+ /**
+ * others IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t received_init;
+
+ /**
+ * our IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t sent_init;
+
+ /**
+ * Current EAP method processing
+ */
+ eap_method_t *method;
+
+ /**
+ * MSK used to build and verify auth payload
+ */
+ chunk_t msk;
+
+ /**
+ * EAP authentication method completed successfully
+ */
+ bool eap_complete;
+
+ /**
+ * Set if we require mutual EAP due EAP-only authentication
+ */
+ bool require_mutual;
+
+ /**
+ * authentication payload verified successfully
+ */
+ bool auth_complete;
+
+ /**
+ * generated EAP payload
+ */
+ eap_payload_t *eap_payload;
+
+ /**
+ * EAP identity of peer
+ */
+ identification_t *eap_identity;
+};
+
+/**
+ * load an EAP method
+ */
+static eap_method_t *load_method(private_eap_authenticator_t *this,
+ eap_type_t type, u_int32_t vendor, eap_role_t role)
+{
+ identification_t *server, *peer;
+
+ if (role == EAP_SERVER)
+ {
+ server = this->ike_sa->get_my_id(this->ike_sa);
+ peer = this->ike_sa->get_other_id(this->ike_sa);
+ }
+ else
+ {
+ server = this->ike_sa->get_other_id(this->ike_sa);
+ peer = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ if (this->eap_identity)
+ {
+ peer = this->eap_identity;
+ }
+ return charon->eap->create_instance(charon->eap, type, vendor,
+ role, server, peer);
+}
+
+/**
+ * Initiate EAP conversation as server
+ */
+static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
+ bool do_identity)
+{
+ auth_cfg_t *auth;
+ eap_type_t type;
+ identification_t *id;
+ u_int32_t vendor;
+ eap_payload_t *out;
+ char *action;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+
+ /* initiate EAP-Identity exchange if required */
+ if (!this->eap_identity && do_identity)
+ {
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
+ if (this->method)
+ {
+ if (this->method->initiate(this->method, &out) == NEED_MORE)
+ {
+ DBG1(DBG_IKE, "initiating EAP-Identity request");
+ return out;
+ }
+ this->method->destroy(this->method);
+ }
+ DBG1(DBG_IKE, "EAP-Identity request configured, but not supported");
+ }
+ }
+ /* invoke real EAP method */
+ type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
+ vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
+ action = "loading";
+ this->method = load_method(this, type, vendor, EAP_SERVER);
+ if (this->method)
+ {
+ action = "initiating";
+ if (this->method->initiate(this->method, &out) == NEED_MORE)
+ {
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method",
+ type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "initiating %N method", eap_type_names, type);
+ }
+ return out;
+ }
+ }
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "%s EAP vendor type %d-%d method failed",
+ action, type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "%s %N method failed", action, eap_type_names, type);
+ }
+ return eap_payload_create_code(EAP_FAILURE, 0);
+}
+
+/**
+ * Replace the existing EAP-Identity in other auth config
+ */
+static void replace_eap_identity(private_eap_authenticator_t *this)
+{
+ enumerator_t *enumerator;
+ auth_rule_t rule;
+ auth_cfg_t *cfg;
+ void *ptr;
+
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ enumerator = cfg->create_enumerator(cfg);
+ while (enumerator->enumerate(enumerator, &rule, &ptr))
+ {
+ if (rule == AUTH_RULE_EAP_IDENTITY)
+ {
+ cfg->replace(cfg, enumerator, AUTH_RULE_EAP_IDENTITY,
+ this->eap_identity->clone(this->eap_identity));
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Handle EAP exchange as server
+ */
+static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
+ eap_payload_t *in)
+{
+ eap_type_t type, received_type;
+ u_int32_t vendor, received_vendor;
+ eap_payload_t *out;
+ auth_cfg_t *cfg;
+
+ if (in->get_code(in) != EAP_RESPONSE)
+ {
+ DBG1(DBG_IKE, "received %N, sending %N",
+ eap_code_names, in->get_code(in), eap_code_names, EAP_FAILURE);
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
+ }
+
+ type = this->method->get_type(this->method, &vendor);
+ received_type = in->get_type(in, &received_vendor);
+ if (type != received_type || vendor != received_vendor)
+ {
+ if (received_vendor == 0 && received_type == EAP_NAK)
+ {
+ DBG1(DBG_IKE, "received %N, sending %N",
+ eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received invalid EAP response, sending %N",
+ eap_code_names, EAP_FAILURE);
+ }
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
+ }
+
+ switch (this->method->process(this->method, in, &out))
+ {
+ case NEED_MORE:
+ return out;
+ case SUCCESS:
+ if (!vendor && type == EAP_IDENTITY)
+ {
+ chunk_t data;
+
+ if (this->method->get_msk(this->method, &data) == SUCCESS)
+ {
+ this->eap_identity = identification_create_from_data(data);
+ DBG1(DBG_IKE, "received EAP identity '%Y'",
+ this->eap_identity);
+ replace_eap_identity(this);
+ }
+ /* restart EAP exchange, but with real method */
+ this->method->destroy(this->method);
+ return server_initiate_eap(this, FALSE);
+ }
+ if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
+ {
+ this->msk = chunk_clone(this->msk);
+ }
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
+ "%sMSK established", type, vendor,
+ this->msk.ptr ? "" : "no ");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
+ eap_type_names, type, this->msk.ptr ? "" : "no ");
+ }
+ this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
+ TRUE);
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ this->eap_complete = TRUE;
+ return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
+ case FAILED:
+ default:
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
+ "peer %Y", type, vendor,
+ this->ike_sa->get_other_id(this->ike_sa));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP method %N failed for peer %Y",
+ eap_type_names, type,
+ this->ike_sa->get_other_id(this->ike_sa));
+ }
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
+ }
+}
+
+/**
+ * Processing method for a peer
+ */
+static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
+ eap_payload_t *in)
+{
+ eap_type_t type;
+ u_int32_t vendor;
+ auth_cfg_t *auth;
+ eap_payload_t *out;
+ identification_t *id;
+
+ type = in->get_type(in, &vendor);
+
+ if (!vendor && type == EAP_IDENTITY)
+ {
+ DESTROY_IF(this->eap_identity);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (!id || id->get_type(id) == ID_ANY)
+ {
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ DBG1(DBG_IKE, "server requested %N, sending '%Y'",
+ eap_type_names, type, id);
+ this->eap_identity = id->clone(id);
+
+ this->method = load_method(this, type, vendor, EAP_PEER);
+ if (this->method)
+ {
+ if (this->method->process(this->method, in, &out) == SUCCESS)
+ {
+ this->method->destroy(this->method);
+ this->method = NULL;
+ return out;
+ }
+ this->method->destroy(this->method);
+ this->method = NULL;
+ }
+ DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
+ eap_type_names, type);
+ return eap_payload_create_nak(in->get_identifier(in));
+ }
+ if (this->method == NULL)
+ {
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d",
+ type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "server requested %N authentication",
+ eap_type_names, type);
+ }
+ this->method = load_method(this, type, vendor, EAP_PEER);
+ if (!this->method)
+ {
+ DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
+ return eap_payload_create_nak(in->get_identifier(in));
+ }
+ }
+
+ type = this->method->get_type(this->method, &vendor);
+
+ if (this->method->process(this->method, in, &out) == NEED_MORE)
+ { /* client methods should never return SUCCESS */
+ return out;
+ }
+
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
+ }
+ return NULL;
+}
+
+/**
+ * Verify AUTH payload
+ */
+static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
+ chunk_t nonce, chunk_t init)
+{
+ auth_payload_t *auth_payload;
+ chunk_t auth_data, recv_auth_data;
+ identification_t *other_id;
+ auth_cfg_t *auth;
+ keymat_t *keymat;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message,
+ AUTHENTICATION);
+ if (!auth_payload)
+ {
+ DBG1(DBG_IKE, "AUTH payload missing");
+ return FALSE;
+ }
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ auth_data = keymat->get_psk_sig(keymat, TRUE, init, nonce,
+ this->msk, other_id);
+ recv_auth_data = auth_payload->get_data(auth_payload);
+ if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
+ {
+ DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
+ this->msk.ptr ? "" : "out");
+ chunk_free(&auth_data);
+ return FALSE;
+ }
+ chunk_free(&auth_data);
+
+ DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
+ other_id, auth_class_names, AUTH_CLASS_EAP);
+ this->auth_complete = TRUE;
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+ return TRUE;
+}
+
+/**
+ * Build AUTH payload
+ */
+static void build_auth(private_eap_authenticator_t *this, message_t *message,
+ chunk_t nonce, chunk_t init)
+{
+ auth_payload_t *auth_payload;
+ identification_t *my_id;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+
+ DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
+ my_id, auth_class_names, AUTH_CLASS_EAP);
+
+ auth_data = keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk, my_id);
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, AUTH_PSK);
+ auth_payload->set_data(auth_payload, auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
+ chunk_free(&auth_data);
+}
+
+/**
+ * Implementation of authenticator_t.process for a server
+ */
+static status_t process_server(private_eap_authenticator_t *this,
+ message_t *message)
+{
+ eap_payload_t *eap_payload;
+
+ if (this->eap_complete)
+ {
+ if (!verify_auth(this, message, this->sent_nonce, this->received_init))
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+
+ if (!this->method)
+ {
+ this->eap_payload = server_initiate_eap(this, TRUE);
+ }
+ else
+ {
+ eap_payload = (eap_payload_t*)message->get_payload(message,
+ EXTENSIBLE_AUTHENTICATION);
+ if (!eap_payload)
+ {
+ return FAILED;
+ }
+ this->eap_payload = server_process_eap(this, eap_payload);
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of authenticator_t.build for a server
+ */
+static status_t build_server(private_eap_authenticator_t *this,
+ message_t *message)
+{
+ if (this->eap_payload)
+ {
+ eap_code_t code;
+
+ code = this->eap_payload->get_code(this->eap_payload);
+ message->add_payload(message, (payload_t*)this->eap_payload);
+ this->eap_payload = NULL;
+ if (code == EAP_FAILURE)
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+ if (this->eap_complete && this->auth_complete)
+ {
+ build_auth(this, message, this->received_nonce, this->sent_init);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of authenticator_t.process for a client
+ */
+static status_t process_client(private_eap_authenticator_t *this,
+ message_t *message)
+{
+ eap_payload_t *eap_payload;
+
+ if (this->eap_complete)
+ {
+ if (!verify_auth(this, message, this->sent_nonce, this->received_init))
+ {
+ return FAILED;
+ }
+ if (this->require_mutual && !this->method->is_mutual(this->method))
+ { /* we require mutual authentication due to EAP-only */
+ u_int32_t vendor;
+
+ DBG1(DBG_IKE, "EAP-only authentication requires a mutual and "
+ "MSK deriving EAP method, but %N is not",
+ eap_type_names, this->method->get_type(this->method, &vendor));
+ return FAILED;
+ }
+ return SUCCESS;
+ }
+
+ eap_payload = (eap_payload_t*)message->get_payload(message,
+ EXTENSIBLE_AUTHENTICATION);
+ if (eap_payload)
+ {
+ switch (eap_payload->get_code(eap_payload))
+ {
+ case EAP_REQUEST:
+ {
+ this->eap_payload = client_process_eap(this, eap_payload);
+ if (this->eap_payload)
+ {
+ return NEED_MORE;
+ }
+ return FAILED;
+ }
+ case EAP_SUCCESS:
+ {
+ eap_type_t type;
+ u_int32_t vendor;
+ auth_cfg_t *cfg;
+
+ if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
+ {
+ this->msk = chunk_clone(this->msk);
+ }
+ type = this->method->get_type(this->method, &vendor);
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
+ "%sMSK established", type, vendor,
+ this->msk.ptr ? "" : "no ");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
+ eap_type_names, type, this->msk.ptr ? "" : "no ");
+ }
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ this->eap_complete = TRUE;
+ return NEED_MORE;
+ }
+ case EAP_FAILURE:
+ default:
+ {
+ DBG1(DBG_IKE, "received %N, EAP authentication failed",
+ eap_code_names, eap_payload->get_code(eap_payload));
+ return FAILED;
+ }
+ }
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of authenticator_t.build for a client
+ */
+static status_t build_client(private_eap_authenticator_t *this,
+ message_t *message)
+{
+ if (this->eap_payload)
+ {
+ message->add_payload(message, (payload_t*)this->eap_payload);
+ this->eap_payload = NULL;
+ return NEED_MORE;
+ }
+ if (this->eap_complete)
+ {
+ build_auth(this, message, this->received_nonce, this->sent_init);
+ return NEED_MORE;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of authenticator_t.is_mutual.
+ */
+static bool is_mutual(private_eap_authenticator_t *this)
+{
+ /* we don't know yet, but insist on it after EAP is complete */
+ this->require_mutual = TRUE;
+ return TRUE;
+}
+
+/**
+ * Implementation of authenticator_t.destroy.
+ */
+static void destroy(private_eap_authenticator_t *this)
+{
+ DESTROY_IF(this->method);
+ DESTROY_IF(this->eap_payload);
+ DESTROY_IF(this->eap_identity);
+ chunk_free(&this->msk);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init)
+{
+ private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build_client;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_client;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))is_mutual;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->received_init = received_init;
+ this->received_nonce = received_nonce;
+ this->sent_init = sent_init;
+ this->sent_nonce = sent_nonce;
+ this->msk = chunk_empty;
+ this->method = NULL;
+ this->eap_payload = NULL;
+ this->eap_complete = FALSE;
+ this->auth_complete = FALSE;
+ this->eap_identity = NULL;
+ this->require_mutual = FALSE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init)
+{
+ private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))build_server;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_server;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))is_mutual;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->received_init = received_init;
+ this->received_nonce = received_nonce;
+ this->sent_init = sent_init;
+ this->sent_nonce = sent_nonce;
+ this->msk = chunk_empty;
+ this->method = NULL;
+ this->eap_payload = NULL;
+ this->eap_complete = FALSE;
+ this->auth_complete = FALSE;
+ this->eap_identity = NULL;
+ this->require_mutual = FALSE;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.h b/src/libcharon/sa/authenticators/eap_authenticator.h
new file mode 100644
index 000000000..41eb6a8c9
--- /dev/null
+++ b/src/libcharon/sa/authenticators/eap_authenticator.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2006-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 eap_authenticator eap_authenticator
+ * @{ @ingroup authenticators
+ */
+
+#ifndef EAP_AUTHENTICATOR_H_
+#define EAP_AUTHENTICATOR_H_
+
+typedef struct eap_authenticator_t eap_authenticator_t;
+
+#include <sa/authenticators/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using EAP authentication.
+ *
+ * Authentication using EAP involves the most complex authenticator. It stays
+ * alive over multiple ike_auth transactions and handles multiple EAP
+ * messages.
+ *
+ * @verbatim
+ ike_sa_init
+ ------------------------->
+ <-------------------------
+ followed by multiple ike_auth:
+
+ +--------+ +--------+
+ | EAP | IDi, [IDr,] SA, TS | EAP |
+ | client | ---------------------------> | server |
+ | | ID, AUTH, EAP | |
+ | | <--------------------------- | |
+ | | EAP | |
+ | | ---------------------------> | |
+ | | EAP | |
+ | | <--------------------------- | |
+ | | EAP | |
+ | | ---------------------------> | |
+ | | EAP(SUCCESS) | |
+ | | <--------------------------- | |
+ | | AUTH | | If EAP establishes
+ | | ---------------------------> | | a session key, AUTH
+ | | AUTH, SA, TS | | payloads use this
+ | | <--------------------------- | | key, not SK_pi/pr
+ +--------+ +--------+
+
+ @endverbatim
+ */
+struct eap_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to authenticate against an EAP server.
+ *
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return EAP authenticator
+ */
+eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init);
+
+/**
+ * Create an authenticator to authenticate EAP clients.
+ *
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return EAP authenticator
+ */
+eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_nonce,
+ chunk_t received_init, chunk_t sent_init);
+
+#endif /** EAP_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c
new file mode 100644
index 000000000..67197d690
--- /dev/null
+++ b/src/libcharon/sa/authenticators/psk_authenticator.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "psk_authenticator.h"
+
+#include <daemon.h>
+#include <encoding/payloads/auth_payload.h>
+
+typedef struct private_psk_authenticator_t private_psk_authenticator_t;
+
+/**
+ * Private data of an psk_authenticator_t object.
+ */
+struct private_psk_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ psk_authenticator_t public;
+
+ /**
+ * Assigned IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * nonce to include in AUTH calculation
+ */
+ chunk_t nonce;
+
+ /**
+ * IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t ike_sa_init;
+};
+
+/*
+ * Implementation of authenticator_t.build for builder
+ */
+static status_t build(private_psk_authenticator_t *this, message_t *message)
+{
+ identification_t *my_id, *other_id;
+ auth_payload_t *auth_payload;
+ shared_key_t *key;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
+ my_id, auth_method_names, AUTH_PSK);
+ key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
+ my_id, other_id);
+ if (key == NULL)
+ {
+ DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
+ return NOT_FOUND;
+ }
+ auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
+ this->nonce, key->get_key(key), my_id);
+ key->destroy(key);
+ DBG2(DBG_IKE, "successfully created shared key MAC");
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, AUTH_PSK);
+ auth_payload->set_data(auth_payload, auth_data);
+ chunk_free(&auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of authenticator_t.process for verifier
+ */
+static status_t process(private_psk_authenticator_t *this, message_t *message)
+{
+ chunk_t auth_data, recv_auth_data;
+ identification_t *my_id, *other_id;
+ auth_payload_t *auth_payload;
+ auth_cfg_t *auth;
+ shared_key_t *key;
+ enumerator_t *enumerator;
+ bool authenticated = FALSE;
+ int keys_found = 0;
+ keymat_t *keymat;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (!auth_payload)
+ {
+ return FAILED;
+ }
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ recv_auth_data = auth_payload->get_data(auth_payload);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ enumerator = charon->credentials->create_shared_enumerator(
+ charon->credentials, SHARED_IKE, my_id, other_id);
+ while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
+ {
+ keys_found++;
+
+ auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
+ this->nonce, key->get_key(key), other_id);
+ if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
+ {
+ DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
+ other_id, auth_method_names, AUTH_PSK);
+ authenticated = TRUE;
+ }
+ chunk_free(&auth_data);
+ }
+ enumerator->destroy(enumerator);
+
+ if (!authenticated)
+ {
+ if (keys_found == 0)
+ {
+ DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
+ return NOT_FOUND;
+ }
+ DBG1(DBG_IKE, "tried %d shared key%s for '%Y' - '%Y', but MAC mismatched",
+ keys_found, keys_found == 1 ? "" : "s", my_id, other_id);
+ return FAILED;
+ }
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of authenticator_t.process for builder
+ * Implementation of authenticator_t.build for verifier
+ */
+static status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of authenticator_t.destroy.
+ */
+static void destroy(private_psk_authenticator_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init)
+{
+ private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = sent_init;
+ this->nonce = received_nonce;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init)
+{
+ private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = received_init;
+ this->nonce = sent_nonce;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.h b/src/libcharon/sa/authenticators/psk_authenticator.h
new file mode 100644
index 000000000..0fab11095
--- /dev/null
+++ b/src/libcharon/sa/authenticators/psk_authenticator.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006-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 psk_authenticator psk_authenticator
+ * @{ @ingroup authenticators
+ */
+
+#ifndef PSK_AUTHENTICATOR_H_
+#define PSK_AUTHENTICATOR_H_
+
+typedef struct psk_authenticator_t psk_authenticator_t;
+
+#include <sa/authenticators/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using pre-shared keys.
+ */
+struct psk_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to build PSK signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return PSK authenticator
+ */
+psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init);
+
+/**
+ * Create an authenticator to verify PSK signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return PSK authenticator
+ */
+psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init);
+
+#endif /** PSK_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c
new file mode 100644
index 000000000..f1dca2702
--- /dev/null
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pubkey_authenticator.h"
+
+#include <daemon.h>
+#include <encoding/payloads/auth_payload.h>
+
+typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t;
+
+/**
+ * Private data of an pubkey_authenticator_t object.
+ */
+struct private_pubkey_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ pubkey_authenticator_t public;
+
+ /**
+ * Assigned IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * nonce to include in AUTH calculation
+ */
+ chunk_t nonce;
+
+ /**
+ * IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t ike_sa_init;
+};
+
+/**
+ * Implementation of authenticator_t.build for builder
+ */
+static status_t build(private_pubkey_authenticator_t *this, message_t *message)
+{
+ chunk_t octets, auth_data;
+ status_t status = FAILED;
+ private_key_t *private;
+ identification_t *id;
+ auth_cfg_t *auth;
+ auth_payload_t *auth_payload;
+ auth_method_t auth_method;
+ signature_scheme_t scheme;
+ keymat_t *keymat;
+
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ private = charon->credentials->get_private(charon->credentials, KEY_ANY,
+ id, auth);
+ if (private == NULL)
+ {
+ DBG1(DBG_IKE, "no private key found for '%Y'", id);
+ return NOT_FOUND;
+ }
+
+ switch (private->get_type(private))
+ {
+ case KEY_RSA:
+ /* we currently use always SHA1 for signatures,
+ * TODO: support other hashes depending on configuration/auth */
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ auth_method = AUTH_RSA;
+ break;
+ case KEY_ECDSA:
+ /* we try to deduct the signature scheme from the keysize */
+ switch (private->get_keysize(private))
+ {
+ case 32:
+ scheme = SIGN_ECDSA_256;
+ auth_method = AUTH_ECDSA_256;
+ break;
+ case 48:
+ scheme = SIGN_ECDSA_384;
+ auth_method = AUTH_ECDSA_384;
+ break;
+ case 66:
+ scheme = SIGN_ECDSA_521;
+ auth_method = AUTH_ECDSA_521;
+ break;
+ default:
+ DBG1(DBG_IKE, "%d bit ECDSA private key size not supported",
+ private->get_keysize(private));
+ return status;
+ }
+ break;
+ default:
+ DBG1(DBG_IKE, "private key of type %N not supported",
+ key_type_names, private->get_type(private));
+ return status;
+ }
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
+ this->nonce, id);
+ if (private->sign(private, scheme, octets, &auth_data))
+ {
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, auth_method);
+ auth_payload->set_data(auth_payload, auth_data);
+ chunk_free(&auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
+ status = SUCCESS;
+ }
+ DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
+ auth_method_names, auth_method,
+ (status == SUCCESS)? "successful":"failed");
+ chunk_free(&octets);
+ private->destroy(private);
+
+ return status;
+}
+
+/**
+ * Implementation of authenticator_t.process for verifier
+ */
+static status_t process(private_pubkey_authenticator_t *this, message_t *message)
+{
+ public_key_t *public;
+ auth_method_t auth_method;
+ auth_payload_t *auth_payload;
+ chunk_t auth_data, octets;
+ identification_t *id;
+ auth_cfg_t *auth, *current_auth;
+ enumerator_t *enumerator;
+ key_type_t key_type = KEY_ECDSA;
+ signature_scheme_t scheme;
+ status_t status = NOT_FOUND;
+ keymat_t *keymat;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (!auth_payload)
+ {
+ return FAILED;
+ }
+ auth_method = auth_payload->get_auth_method(auth_payload);
+ switch (auth_method)
+ {
+ case AUTH_RSA:
+ /* We currently accept SHA1 signatures only
+ * TODO: allow other hash algorithms and note it in "auth" */
+ key_type = KEY_RSA;
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ break;
+ case AUTH_ECDSA_256:
+ scheme = SIGN_ECDSA_256;
+ break;
+ case AUTH_ECDSA_384:
+ scheme = SIGN_ECDSA_384;
+ break;
+ case AUTH_ECDSA_521:
+ scheme = SIGN_ECDSA_521;
+ break;
+ default:
+ return INVALID_ARG;
+ }
+ auth_data = auth_payload->get_data(auth_payload);
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
+ this->nonce, id);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ enumerator = charon->credentials->create_public_enumerator(
+ charon->credentials, key_type, id, auth);
+ while (enumerator->enumerate(enumerator, &public, &current_auth))
+ {
+ if (public->verify(public, scheme, octets, auth_data))
+ {
+ DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
+ id, auth_method_names, auth_method);
+ status = SUCCESS;
+ auth->merge(auth, current_auth, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ break;
+ }
+ else
+ {
+ status = FAILED;
+ DBG1(DBG_IKE, "signature validation failed, looking for another key");
+ }
+ }
+ enumerator->destroy(enumerator);
+ chunk_free(&octets);
+ if (status == NOT_FOUND)
+ {
+ DBG1(DBG_IKE, "no trusted %N public key found for '%Y'",
+ key_type_names, key_type, id);
+ }
+ return status;
+}
+
+/**
+ * Implementation of authenticator_t.process for builder
+ * Implementation of authenticator_t.build for verifier
+ */
+static status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of authenticator_t.destroy.
+ */
+static void destroy(private_pubkey_authenticator_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init)
+{
+ private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = sent_init;
+ this->nonce = received_nonce;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init)
+{
+ private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
+ this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = received_init;
+ this->nonce = sent_nonce;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.h b/src/libcharon/sa/authenticators/pubkey_authenticator.h
new file mode 100644
index 000000000..be369cb89
--- /dev/null
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2006-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 pubkey_authenticator pubkey_authenticator
+ * @{ @ingroup authenticators
+ */
+
+#ifndef PUBKEY_AUTHENTICATOR_H_
+#define PUBKEY_AUTHENTICATOR_H_
+
+typedef struct pubkey_authenticator_t pubkey_authenticator_t;
+
+#include <sa/authenticators/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using public key authenitcation.
+ */
+struct pubkey_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to build public key signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return public key authenticator
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init);
+
+/**
+ * Create an authenticator to verify public key signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return public key authenticator
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init);
+
+#endif /** PUBKEY_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
new file mode 100644
index 000000000..3fdfb51ad
--- /dev/null
+++ b/src/libcharon/sa/child_sa.c
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (C) 2006-2009 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+#include "child_sa.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <daemon.h>
+
+ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
+ "CREATED",
+ "ROUTED",
+ "INSTALLING",
+ "INSTALLED",
+ "UPDATING",
+ "REKEYING",
+ "DELETING",
+ "DESTROYING",
+);
+
+typedef struct private_child_sa_t private_child_sa_t;
+
+/**
+ * Private data of a child_sa_t object.
+ */
+struct private_child_sa_t {
+ /**
+ * Public interface of child_sa_t.
+ */
+ child_sa_t public;
+
+ /**
+ * address of us
+ */
+ host_t *my_addr;
+
+ /**
+ * address of remote
+ */
+ host_t *other_addr;
+
+ /**
+ * our actually used SPI, 0 if unused
+ */
+ u_int32_t my_spi;
+
+ /**
+ * others used SPI, 0 if unused
+ */
+ u_int32_t other_spi;
+
+ /**
+ * our Compression Parameter Index (CPI) used, 0 if unused
+ */
+ u_int16_t my_cpi;
+
+ /**
+ * others Compression Parameter Index (CPI) used, 0 if unused
+ */
+ u_int16_t other_cpi;
+
+ /**
+ * List for local traffic selectors
+ */
+ linked_list_t *my_ts;
+
+ /**
+ * List for remote traffic selectors
+ */
+ linked_list_t *other_ts;
+
+ /**
+ * Protocol used to protect this SA, ESP|AH
+ */
+ protocol_id_t protocol;
+
+ /**
+ * reqid used for this child_sa
+ */
+ u_int32_t reqid;
+
+ /**
+ * absolute time when rekeying is scheduled
+ */
+ time_t rekey_time;
+
+ /**
+ * absolute time when the SA expires
+ */
+ time_t expire_time;
+
+ /**
+ * state of the CHILD_SA
+ */
+ child_sa_state_t state;
+
+ /**
+ * Specifies if UDP encapsulation is enabled (NAT traversal)
+ */
+ bool encap;
+
+ /**
+ * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
+ */
+ ipcomp_transform_t ipcomp;
+
+ /**
+ * mode this SA uses, tunnel/transport
+ */
+ ipsec_mode_t mode;
+
+ /**
+ * selected proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * config used to create this child
+ */
+ child_cfg_t *config;
+
+ /**
+ * time of last use in seconds (inbound)
+ */
+ u_int32_t my_usetime;
+
+ /**
+ * time of last use in seconds (outbound)
+ */
+ u_int32_t other_usetime;
+
+ /**
+ * last number of inbound bytes
+ */
+ u_int64_t my_usebytes;
+
+ /**
+ * last number of outbound bytes
+ */
+ u_int64_t other_usebytes;
+};
+
+/**
+ * Implementation of child_sa_t.get_name
+ */
+static char *get_name(private_child_sa_t *this)
+{
+ return this->config->get_name(this->config);
+}
+
+/**
+ * Implements child_sa_t.get_reqid
+ */
+static u_int32_t get_reqid(private_child_sa_t *this)
+{
+ return this->reqid;
+}
+
+/**
+ * Implements child_sa_t.get_config
+ */
+static child_cfg_t* get_config(private_child_sa_t *this)
+{
+ return this->config;
+}
+
+/**
+ * Implements child_sa_t.set_state
+ */
+static void set_state(private_child_sa_t *this, child_sa_state_t state)
+{
+ charon->bus->child_state_change(charon->bus, &this->public, state);
+ this->state = state;
+}
+
+/**
+ * Implements child_sa_t.get_state
+ */
+static child_sa_state_t get_state(private_child_sa_t *this)
+{
+ return this->state;
+}
+
+/**
+ * Implements child_sa_t.get_spi
+ */
+u_int32_t get_spi(private_child_sa_t *this, bool inbound)
+{
+ return inbound ? this->my_spi : this->other_spi;
+}
+
+/**
+ * Implements child_sa_t.get_cpi
+ */
+u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
+{
+ return inbound ? this->my_cpi : this->other_cpi;
+}
+
+/**
+ * Implements child_sa_t.get_protocol
+ */
+protocol_id_t get_protocol(private_child_sa_t *this)
+{
+ return this->protocol;
+}
+
+/**
+ * Implementation of child_sa_t.set_protocol
+ */
+static void set_protocol(private_child_sa_t *this, protocol_id_t protocol)
+{
+ this->protocol = protocol;
+}
+
+/**
+ * Implementation of child_sa_t.get_mode
+ */
+static ipsec_mode_t get_mode(private_child_sa_t *this)
+{
+ return this->mode;
+}
+
+/**
+ * Implementation of child_sa_t.set_mode
+ */
+static void set_mode(private_child_sa_t *this, ipsec_mode_t mode)
+{
+ this->mode = mode;
+}
+
+/**
+ * Implementation of child_sa_t.has_encap
+ */
+static bool has_encap(private_child_sa_t *this)
+{
+ return this->encap;
+}
+
+/**
+ * Implementation of child_sa_t.get_ipcomp
+ */
+static ipcomp_transform_t get_ipcomp(private_child_sa_t *this)
+{
+ return this->ipcomp;
+}
+
+/**
+ * Implementation of child_sa_t.set_ipcomp.
+ */
+static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp)
+{
+ this->ipcomp = ipcomp;
+}
+
+/**
+ * Implementation of child_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_child_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of child_sa_t.set_proposal
+ */
+static void set_proposal(private_child_sa_t *this, proposal_t *proposal)
+{
+ this->proposal = proposal->clone(proposal);
+}
+
+/**
+ * Implementation of child_sa_t.get_traffic_selectors.
+ */
+static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
+{
+ return local ? this->my_ts : this->other_ts;
+}
+
+typedef struct policy_enumerator_t policy_enumerator_t;
+
+/**
+ * Private policy enumerator
+ */
+struct policy_enumerator_t {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over own TS */
+ enumerator_t *mine;
+ /** enumerator over others TS */
+ enumerator_t *other;
+ /** list of others TS, to recreate enumerator */
+ linked_list_t *list;
+ /** currently enumerating TS for "me" side */
+ traffic_selector_t *ts;
+};
+
+/**
+ * enumerator function of create_policy_enumerator()
+ */
+static bool policy_enumerate(policy_enumerator_t *this,
+ traffic_selector_t **my_out, traffic_selector_t **other_out)
+{
+ traffic_selector_t *other_ts;
+
+ while (this->ts || this->mine->enumerate(this->mine, &this->ts))
+ {
+ if (!this->other->enumerate(this->other, &other_ts))
+ { /* end of others list, restart with new of mine */
+ this->other->destroy(this->other);
+ this->other = this->list->create_enumerator(this->list);
+ this->ts = NULL;
+ continue;
+ }
+ if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
+ { /* family mismatch */
+ continue;
+ }
+ if (this->ts->get_protocol(this->ts) &&
+ other_ts->get_protocol(other_ts) &&
+ this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
+ { /* protocol mismatch */
+ continue;
+ }
+ *my_out = this->ts;
+ *other_out = other_ts;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function of create_policy_enumerator()
+ */
+static void policy_destroy(policy_enumerator_t *this)
+{
+ this->mine->destroy(this->mine);
+ this->other->destroy(this->other);
+ free(this);
+}
+
+/**
+ * Implementation of child_sa_t.create_policy_enumerator
+ */
+static enumerator_t* create_policy_enumerator(private_child_sa_t *this)
+{
+ policy_enumerator_t *e = malloc_thing(policy_enumerator_t);
+
+ e->public.enumerate = (void*)policy_enumerate;
+ e->public.destroy = (void*)policy_destroy;
+ e->mine = this->my_ts->create_enumerator(this->my_ts);
+ e->other = this->other_ts->create_enumerator(this->other_ts);
+ e->list = this->other_ts;
+ e->ts = NULL;
+
+ return &e->public;
+}
+
+/**
+ * update the cached usebytes
+ * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
+ * are available, and NOT_SUPPORTED if the kernel interface does not support
+ * querying the usebytes.
+ */
+static status_t update_usebytes(private_child_sa_t *this, bool inbound)
+{
+ status_t status = FAILED;
+ u_int64_t bytes;
+
+ if (inbound)
+ {
+ if (this->my_spi)
+ {
+ status = charon->kernel_interface->query_sa(
+ charon->kernel_interface,
+ this->other_addr, this->my_addr,
+ this->my_spi, this->protocol, &bytes);
+ if (status == SUCCESS)
+ {
+ if (bytes > this->my_usebytes)
+ {
+ this->my_usebytes = bytes;
+ return SUCCESS;
+ }
+ return FAILED;
+ }
+ }
+ }
+ else
+ {
+ if (this->other_spi)
+ {
+ status = charon->kernel_interface->query_sa(
+ charon->kernel_interface,
+ this->my_addr, this->other_addr,
+ this->other_spi, this->protocol, &bytes);
+ if (status == SUCCESS)
+ {
+ if (bytes > this->other_usebytes)
+ {
+ this->other_usebytes = bytes;
+ return SUCCESS;
+ }
+ return FAILED;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * updates the cached usetime
+ */
+static void update_usetime(private_child_sa_t *this, bool inbound)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ u_int32_t last_use = 0;
+
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ u_int32_t in, out, fwd;
+
+ if (inbound)
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
+ {
+ last_use = max(last_use, in);
+ }
+ if (this->mode != MODE_TRANSPORT)
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
+ {
+ last_use = max(last_use, fwd);
+ }
+ }
+ }
+ else
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
+ {
+ last_use = max(last_use, out);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (last_use == 0)
+ {
+ return;
+ }
+ if (inbound)
+ {
+ this->my_usetime = last_use;
+ }
+ else
+ {
+ this->other_usetime = last_use;
+ }
+}
+
+/**
+ * Implementation of child_sa_t.get_usestats
+ */
+static void get_usestats(private_child_sa_t *this, bool inbound,
+ time_t *time, u_int64_t *bytes)
+{
+ if (update_usebytes(this, inbound) != FAILED)
+ {
+ /* there was traffic since last update or the kernel interface
+ * does not support querying the number of usebytes.
+ */
+ update_usetime(this, inbound);
+ }
+ if (time)
+ {
+ *time = inbound ? this->my_usetime : this->other_usetime;
+ }
+ if (bytes)
+ {
+ *bytes = inbound ? this->my_usebytes : this->other_usebytes;
+ }
+}
+
+/**
+ * Implementation of child_sa_t.get_lifetime
+ */
+static time_t get_lifetime(private_child_sa_t *this, bool hard)
+{
+ return hard ? this->expire_time : this->rekey_time;
+}
+
+/**
+ * Implementation of child_sa_t.alloc_spi
+ */
+static u_int32_t alloc_spi(private_child_sa_t *this, protocol_id_t protocol)
+{
+ if (charon->kernel_interface->get_spi(charon->kernel_interface,
+ this->other_addr, this->my_addr, protocol,
+ this->reqid, &this->my_spi) == SUCCESS)
+ {
+ return this->my_spi;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of child_sa_t.alloc_cpi
+ */
+static u_int16_t alloc_cpi(private_child_sa_t *this)
+{
+ if (charon->kernel_interface->get_cpi(charon->kernel_interface,
+ this->other_addr, this->my_addr, this->reqid,
+ &this->my_cpi) == SUCCESS)
+ {
+ return this->my_cpi;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of child_sa_t.install
+ */
+static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
+ u_int32_t spi, u_int16_t cpi, bool inbound,
+ linked_list_t *my_ts, linked_list_t *other_ts)
+{
+ u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
+ traffic_selector_t *src_ts = NULL, *dst_ts = NULL;
+ time_t now;
+ lifetime_cfg_t *lifetime;
+ host_t *src, *dst;
+ status_t status;
+ bool update = FALSE;
+
+ /* now we have to decide which spi to use. Use self allocated, if "in",
+ * or the one in the proposal, if not "in" (others). Additionally,
+ * source and dest host switch depending on the role */
+ if (inbound)
+ {
+ dst = this->my_addr;
+ src = this->other_addr;
+ if (this->my_spi == spi)
+ { /* alloc_spi has been called, do an SA update */
+ update = TRUE;
+ }
+ this->my_spi = spi;
+ this->my_cpi = cpi;
+ }
+ else
+ {
+ src = this->my_addr;
+ dst = this->other_addr;
+ this->other_spi = spi;
+ this->other_cpi = cpi;
+ }
+
+ DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
+ protocol_id_names, this->protocol);
+
+ /* send SA down to the kernel */
+ DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
+
+ this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &size);
+ this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &size);
+
+ lifetime = this->config->get_lifetime(this->config);
+
+ now = time_monotonic(NULL);
+ if (lifetime->time.rekey)
+ {
+ this->rekey_time = now + lifetime->time.rekey;
+ }
+ if (lifetime->time.life)
+ {
+ this->expire_time = now + lifetime->time.life;
+ }
+
+ if (!lifetime->time.jitter && !inbound)
+ { /* avoid triggering multiple rekey events */
+ lifetime->time.rekey = 0;
+ }
+
+ if (this->mode == MODE_BEET)
+ {
+ /* BEET requires the bound address from the traffic selectors.
+ * TODO: We add just the first traffic selector for now, as the
+ * kernel accepts a single TS per SA only */
+ if (inbound)
+ {
+ my_ts->get_first(my_ts, (void**)&dst_ts);
+ other_ts->get_first(other_ts, (void**)&src_ts);
+ }
+ else
+ {
+ my_ts->get_first(my_ts, (void**)&src_ts);
+ other_ts->get_first(other_ts, (void**)&dst_ts);
+ }
+ }
+
+ status = charon->kernel_interface->add_sa(charon->kernel_interface,
+ src, dst, spi, this->protocol, this->reqid, lifetime,
+ enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
+ this->encap, update, src_ts, dst_ts);
+
+ free(lifetime);
+
+ return status;
+}
+
+/**
+ * Implementation of child_sa_t.add_policies
+ */
+static status_t add_policies(private_child_sa_t *this,
+ linked_list_t *my_ts_list, linked_list_t *other_ts_list)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ status_t status = SUCCESS;
+ bool routed = (this->state == CHILD_CREATED);
+
+ /* apply traffic selectors */
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ while (enumerator->enumerate(enumerator, &my_ts))
+ {
+ this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts));
+ }
+ enumerator->destroy(enumerator);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ while (enumerator->enumerate(enumerator, &other_ts))
+ {
+ this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts));
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->config->install_policy(this->config))
+ {
+ /* enumerate pairs of traffic selectors */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ /* install 3 policies: out, in and forward */
+ status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+ this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
+ this->other_spi, this->protocol, this->reqid, this->mode,
+ this->ipcomp, this->other_cpi, routed);
+
+ status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
+ this->my_spi, this->protocol, this->reqid, this->mode,
+ this->ipcomp, this->my_cpi, routed);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
+ this->my_spi, this->protocol, this->reqid, this->mode,
+ this->ipcomp, this->my_cpi, routed);
+ }
+
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (status == SUCCESS && this->state == CHILD_CREATED)
+ { /* switch to routed state if no SAD entry set up */
+ set_state(this, CHILD_ROUTED);
+ }
+ return status;
+}
+
+/**
+ * Implementation of child_sa_t.update.
+ */
+static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
+ host_t *vip, bool encap)
+{
+ child_sa_state_t old;
+ bool transport_proxy_mode;
+
+ /* anything changed at all? */
+ if (me->equals(me, this->my_addr) &&
+ other->equals(other, this->other_addr) && this->encap == encap)
+ {
+ return SUCCESS;
+ }
+
+ old = this->state;
+ set_state(this, CHILD_UPDATING);
+ transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
+ this->mode == MODE_TRANSPORT;
+
+ if (!transport_proxy_mode)
+ {
+ /* update our (initator) SA */
+ if (this->my_spi)
+ {
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->my_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ this->other_addr, this->my_addr, other, me,
+ this->encap, encap) == NOT_SUPPORTED)
+ {
+ return NOT_SUPPORTED;
+ }
+ }
+
+ /* update his (responder) SA */
+ if (this->other_spi)
+ {
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->other_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ this->my_addr, this->other_addr, me, other,
+ this->encap, encap) == NOT_SUPPORTED)
+ {
+ return NOT_SUPPORTED;
+ }
+ }
+ }
+
+ if (this->config->install_policy(this->config))
+ {
+ /* update policies */
+ if (!me->ip_equals(me, this->my_addr) ||
+ !other->ip_equals(other, this->other_addr))
+ {
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+
+ /* always use high priorities, as hosts getting updated are INSTALLED */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ /* remove old policies first */
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, FALSE);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, FALSE);
+ }
+
+ /* check whether we have to update a "dynamic" traffic selector */
+ if (!me->ip_equals(me, this->my_addr) &&
+ my_ts->is_host(my_ts, this->my_addr))
+ {
+ my_ts->set_address(my_ts, me);
+ }
+ if (!other->ip_equals(other, this->other_addr) &&
+ other_ts->is_host(other_ts, this->other_addr))
+ {
+ other_ts->set_address(other_ts, other);
+ }
+
+ /* we reinstall the virtual IP to handle interface roaming
+ * correctly */
+ if (vip)
+ {
+ charon->kernel_interface->del_ip(charon->kernel_interface, vip);
+ charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
+ }
+
+ /* reinstall updated policies */
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->other_cpi, FALSE);
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+
+ if (!transport_proxy_mode)
+ {
+ /* apply hosts */
+ if (!me->equals(me, this->my_addr))
+ {
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = me->clone(me);
+ }
+ if (!other->equals(other, this->other_addr))
+ {
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = other->clone(other);
+ }
+ }
+
+ this->encap = encap;
+ set_state(this, old);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of child_sa_t.destroy.
+ */
+static void destroy(private_child_sa_t *this)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ bool unrouted = (this->state == CHILD_ROUTED);
+
+ set_state(this, CHILD_DESTROYING);
+
+ /* delete SAs in the kernel, if they are set up */
+ if (this->my_spi)
+ {
+ /* if CHILD was not established, use PROTO_ESP used during alloc_spi().
+ * TODO: For AH support, we have to store protocol specific SPI.s */
+ if (this->protocol == PROTO_NONE)
+ {
+ this->protocol = PROTO_ESP;
+ }
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->other_addr, this->my_addr, this->my_spi,
+ this->protocol, this->my_cpi);
+ }
+ if (this->other_spi)
+ {
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->my_addr, this->other_addr, this->other_spi,
+ this->protocol, this->other_cpi);
+ }
+
+ if (this->config->install_policy(this->config))
+ {
+ /* delete all policies in the kernel */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, unrouted);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, unrouted);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, unrouted);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
+ this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
+ this->my_addr->destroy(this->my_addr);
+ this->other_addr->destroy(this->other_addr);
+ DESTROY_IF(this->proposal);
+ this->config->destroy(this->config);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+child_sa_t * child_sa_create(host_t *me, host_t* other,
+ child_cfg_t *config, u_int32_t rekey, bool encap)
+{
+ static u_int32_t reqid = 0;
+ private_child_sa_t *this = malloc_thing(private_child_sa_t);
+
+ /* public functions */
+ this->public.get_name = (char*(*)(child_sa_t*))get_name;
+ this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
+ this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
+ this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
+ this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
+ this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
+ this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
+ this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
+ this->public.set_protocol = (void(*)(child_sa_t*, protocol_id_t protocol))set_protocol;
+ this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode;
+ this->public.set_mode = (void(*)(child_sa_t*, ipsec_mode_t mode))set_mode;
+ this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
+ this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
+ this->public.get_lifetime = (time_t(*)(child_sa_t*, bool))get_lifetime;
+ this->public.get_usestats = (void(*)(child_sa_t*,bool,time_t*,u_int64_t*))get_usestats;
+ this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
+ this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
+ this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
+ this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
+ this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
+ this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install;
+ this->public.update = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update;
+ this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
+ this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
+ this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
+ this->public.destroy = (void(*)(child_sa_t*))destroy;
+
+ /* private data */
+ this->my_addr = me->clone(me);
+ this->other_addr = other->clone(other);
+ this->my_spi = 0;
+ this->other_spi = 0;
+ this->my_cpi = 0;
+ this->other_cpi = 0;
+ this->encap = encap;
+ this->ipcomp = IPCOMP_NONE;
+ this->state = CHILD_CREATED;
+ this->my_usetime = 0;
+ this->other_usetime = 0;
+ this->my_usebytes = 0;
+ this->other_usebytes = 0;
+ /* reuse old reqid if we are rekeying an existing CHILD_SA */
+ this->reqid = rekey ? rekey : ++reqid;
+ this->my_ts = linked_list_create();
+ this->other_ts = linked_list_create();
+ this->protocol = PROTO_NONE;
+ this->mode = MODE_TUNNEL;
+ this->proposal = NULL;
+ this->rekey_time = 0;
+ this->expire_time = 0;
+ this->config = config;
+ config->get_ref(config);
+
+ /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
+ if (config->get_mode(config) == MODE_TRANSPORT &&
+ config->use_proxy_mode(config))
+ {
+ ts_type_t type;
+ int family;
+ chunk_t addr;
+ host_t *host;
+ enumerator_t *enumerator;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+
+ this->mode = MODE_TRANSPORT;
+
+ my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ if (enumerator->enumerate(enumerator, &my_ts))
+ {
+ if (my_ts->is_host(my_ts, NULL) &&
+ !my_ts->is_host(my_ts, this->my_addr))
+ {
+ type = my_ts->get_type(my_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = my_ts->get_from_address(my_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
+ this->my_addr, host);
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
+
+ other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ if (enumerator->enumerate(enumerator, &other_ts))
+ {
+ if (other_ts->is_host(other_ts, NULL) &&
+ !other_ts->is_host(other_ts, this->other_addr))
+ {
+ type = other_ts->get_type(other_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = other_ts->get_from_address(other_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
+ this->other_addr, host);
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
new file mode 100644
index 000000000..e6c603504
--- /dev/null
+++ b/src/libcharon/sa/child_sa.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * 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 child_sa child_sa
+ * @{ @ingroup sa
+ */
+
+#ifndef CHILD_SA_H_
+#define CHILD_SA_H_
+
+typedef enum child_sa_state_t child_sa_state_t;
+typedef struct child_sa_t child_sa_t;
+
+#include <library.h>
+#include <crypto/prf_plus.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <config/proposal.h>
+#include <config/child_cfg.h>
+
+/**
+ * States of a CHILD_SA
+ */
+enum child_sa_state_t {
+
+ /**
+ * Just created, uninstalled CHILD_SA
+ */
+ CHILD_CREATED,
+
+ /**
+ * Installed SPD, but no SAD entries
+ */
+ CHILD_ROUTED,
+
+ /**
+ * Installing an in-use CHILD_SA
+ */
+ CHILD_INSTALLING,
+
+ /**
+ * Installed an in-use CHILD_SA
+ */
+ CHILD_INSTALLED,
+
+ /**
+ * While updating hosts, in update_hosts()
+ */
+ CHILD_UPDATING,
+
+ /**
+ * CHILD_SA which is rekeying
+ */
+ CHILD_REKEYING,
+
+ /**
+ * CHILD_SA in progress of delete
+ */
+ CHILD_DELETING,
+
+ /**
+ * CHILD_SA object gets destroyed
+ */
+ CHILD_DESTROYING,
+};
+
+/**
+ * enum strings for child_sa_state_t.
+ */
+extern enum_name_t *child_sa_state_names;
+
+/**
+ * Represents an IPsec SAs between two hosts.
+ *
+ * A child_sa_t contains two SAs. SAs for both
+ * directions are managed in one child_sa_t object. Both
+ * SAs and the policies have the same reqid.
+ *
+ * The procedure for child sa setup is as follows:
+ * - A gets SPIs for a all protocols in its proposals via child_sa_t.alloc
+ * - A send the proposals with the allocated SPIs to B
+ * - B selects a suitable proposal
+ * - B allocates an SPI for the selected protocol
+ * - B calls child_sa_t.install for both, the allocated and received SPI
+ * - B sends the proposal with the allocated SPI to A
+ * - A calls child_sa_t.install for both, the allocated and recevied SPI
+ *
+ * Once SAs are set up, policies can be added using add_policies.
+ */
+struct child_sa_t {
+
+ /**
+ * Get the name of the config this CHILD_SA uses.
+ *
+ * @return name
+ */
+ char* (*get_name) (child_sa_t *this);
+
+ /**
+ * Get the reqid of the CHILD SA.
+ *
+ * Every CHILD_SA has a reqid. The kernel uses this ID to
+ * identify it.
+ *
+ * @return reqid of the CHILD SA
+ */
+ u_int32_t (*get_reqid)(child_sa_t *this);
+
+ /**
+ * Get the config used to set up this child sa.
+ *
+ * @return child_cfg
+ */
+ child_cfg_t* (*get_config) (child_sa_t *this);
+
+ /**
+ * Get the state of the CHILD_SA.
+ *
+ * @return CHILD_SA state
+ */
+ child_sa_state_t (*get_state) (child_sa_t *this);
+
+ /**
+ * Set the state of the CHILD_SA.
+ *
+ * @param state state to set on CHILD_SA
+ */
+ void (*set_state) (child_sa_t *this, child_sa_state_t state);
+
+ /**
+ * Get the SPI of this CHILD_SA.
+ *
+ * Set the boolean parameter inbound to TRUE to
+ * get the SPI for which we receive packets, use
+ * FALSE to get those we use for sending packets.
+ *
+ * @param inbound TRUE to get inbound SPI, FALSE for outbound.
+ * @return SPI of the CHILD SA
+ */
+ u_int32_t (*get_spi) (child_sa_t *this, bool inbound);
+
+ /**
+ * Get the CPI of this CHILD_SA.
+ *
+ * Set the boolean parameter inbound to TRUE to
+ * get the CPI for which we receive packets, use
+ * FALSE to get those we use for sending packets.
+ *
+ * @param inbound TRUE to get inbound CPI, FALSE for outbound.
+ * @return CPI of the CHILD SA
+ */
+ u_int16_t (*get_cpi) (child_sa_t *this, bool inbound);
+
+ /**
+ * Get the protocol which this CHILD_SA uses to protect traffic.
+ *
+ * @return AH | ESP
+ */
+ protocol_id_t (*get_protocol) (child_sa_t *this);
+
+ /**
+ * Set the negotiated protocol to use for this CHILD_SA.
+ *
+ * @param protocol AH | ESP
+ */
+ void (*set_protocol)(child_sa_t *this, protocol_id_t protocol);
+
+ /**
+ * Get the IPsec mode of this CHILD_SA.
+ *
+ * @return TUNNEL | TRANSPORT | BEET
+ */
+ ipsec_mode_t (*get_mode)(child_sa_t *this);
+
+ /**
+ * Set the negotiated IPsec mode to use.
+ *
+ * @param mode TUNNEL | TRANPORT | BEET
+ */
+ void (*set_mode)(child_sa_t *this, ipsec_mode_t mode);
+
+ /**
+ * Get the used IPComp algorithm.
+ *
+ * @return IPComp compression algorithm.
+ */
+ ipcomp_transform_t (*get_ipcomp)(child_sa_t *this);
+
+ /**
+ * Set the IPComp algorithm to use.
+ *
+ * @param ipcomp the IPComp transform to use
+ */
+ void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
+
+ /**
+ * Get the selected proposal.
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(child_sa_t *this);
+
+ /**
+ * Set the negotiated proposal.
+ *
+ * @param proposal selected proposal
+ */
+ void (*set_proposal)(child_sa_t *this, proposal_t *proposal);
+
+ /**
+ * Check if this CHILD_SA uses UDP encapsulation.
+ *
+ * @return TRUE if SA encapsulates ESP packets
+ */
+ bool (*has_encap)(child_sa_t *this);
+
+ /**
+ * Get the absolute time when the CHILD_SA expires or gets rekeyed.
+ *
+ * @param hard TRUE for hard lifetime, FALSE for soft (rekey) lifetime
+ * @return absolute time
+ */
+ time_t (*get_lifetime)(child_sa_t *this, bool hard);
+
+ /**
+ * Get last use time and the number of bytes processed.
+ *
+ * @param inbound TRUE for inbound traffic, FALSE for outbound
+ * @param[out] time time of last use in seconds (NULL to ignore)
+ * @param[out] bytes number of processed bytes (NULL to ignore)
+ */
+ void (*get_usestats)(child_sa_t *this, bool inbound, time_t *time,
+ u_int64_t *bytes);
+
+ /**
+ * Get the traffic selectors list added for one side.
+ *
+ * @param local TRUE for own traffic selectors, FALSE for remote
+ * @return list of traffic selectors
+ */
+ linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
+
+ /**
+ * Create an enumerator over installed policies.
+ *
+ * @return enumerator over pairs of traffic selectors.
+ */
+ enumerator_t* (*create_policy_enumerator)(child_sa_t *this);
+
+ /**
+ * Allocate an SPI to include in a proposal.
+ *
+ * @param protocol protocol to allocate SPI for (ESP|AH)
+ * @param spi SPI output pointer
+ * @return SPI, 0 on failure
+ */
+ u_int32_t (*alloc_spi)(child_sa_t *this, protocol_id_t protocol);
+
+ /**
+ * Allocate a CPI to use for IPComp.
+ *
+ * @return CPI, 0 on failure
+ */
+ u_int16_t (*alloc_cpi)(child_sa_t *this);
+
+ /**
+ * Install an IPsec SA for one direction.
+ *
+ * @param encr encryption key, if any
+ * @param integ integrity key
+ * @param spi SPI to use, allocated for inbound
+ * @param cpi CPI to use, allocated for outbound
+ * @param inbound TRUE to install an inbound SA, FALSE for outbound
+ * @param my_ts negotiated local traffic selector list
+ * @param other_ts negotiated remote traffic selector list
+ * @return SUCCESS or FAILED
+ */
+ status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
+ u_int32_t spi, u_int16_t cpi, bool inbound,
+ linked_list_t *my_ts, linked_list_t *other_ts);
+ /**
+ * Install the policies using some traffic selectors.
+ *
+ * Supplied lists of traffic_selector_t's specify the policies
+ * to use for this child sa.
+ *
+ * @param my_ts traffic selectors for local site
+ * @param other_ts traffic selectors for remote site
+ * @return SUCCESS or FAILED
+ */
+ status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
+ linked_list_t *other_ts_list);
+ /**
+ * Update hosts and ecapulation mode in the kernel SAs and policies.
+ *
+ * @param me the new local host
+ * @param other the new remote host
+ * @param vip virtual IP, if any
+ * @param TRUE to use UDP encapsulation for NAT traversal
+ * @return SUCCESS or FAILED
+ */
+ status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
+ host_t *vip, bool encap);
+ /**
+ * Destroys a child_sa.
+ */
+ void (*destroy) (child_sa_t *this);
+};
+
+/**
+ * Constructor to create a child SA negotiated with IKE.
+ *
+ * @param me own address
+ * @param other remote address
+ * @param config config to use for this CHILD_SA
+ * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
+ * @param encap TRUE to enable UDP encapsulation (NAT traversal)
+ * @return child_sa_t object
+ */
+child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
+ u_int32_t reqid, bool encap);
+
+#endif /** CHILD_SA_H_ @}*/
diff --git a/src/libcharon/sa/connect_manager.c b/src/libcharon/sa/connect_manager.c
new file mode 100644
index 000000000..b78ba070d
--- /dev/null
+++ b/src/libcharon/sa/connect_manager.c
@@ -0,0 +1,1623 @@
+/*
+ * Copyright (C) 2007-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 "connect_manager.h"
+
+#include <math.h>
+
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <crypto/hashers/hasher.h>
+
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/initiate_mediation_job.h>
+#include <encoding/payloads/endpoint_notify.h>
+
+/* base timeout
+ * the check interval is ME_INTERVAL */
+#define ME_INTERVAL 25 /* ms */
+/* retransmission timeout is first ME_INTERVAL for ME_BOOST retransmissions
+ * then gets reduced to ME_INTERVAL * ME_RETRANS_BASE ^ (sent retransmissions - ME_BOOST). */
+/* number of initial retransmissions sent in short interval */
+#define ME_BOOST 2
+/* base for retransmissions */
+#define ME_RETRANS_BASE 1.8
+/* max number of retransmissions */
+#define ME_MAX_RETRANS 13
+
+/* time to wait before the initiator finishes the connectivity checks after
+ * the first check has succeeded */
+#define ME_WAIT_TO_FINISH 1000 /* ms */
+
+typedef struct private_connect_manager_t private_connect_manager_t;
+
+/**
+ * Additional private members of connect_manager_t.
+ */
+struct private_connect_manager_t {
+ /**
+ * Public interface of connect_manager_t.
+ */
+ connect_manager_t public;
+
+ /**
+ * Lock for exclusivly accessing the manager.
+ */
+ mutex_t *mutex;
+
+ /**
+ * Hasher to generate signatures
+ */
+ hasher_t *hasher;
+
+ /**
+ * Linked list with initiated mediated connections
+ */
+ linked_list_t *initiated;
+
+ /**
+ * Linked list with checklists (hash table with connect ID as key would
+ * be better).
+ */
+ linked_list_t *checklists;
+};
+
+typedef enum check_state_t check_state_t;
+
+enum check_state_t {
+ CHECK_NONE,
+ CHECK_WAITING,
+ CHECK_IN_PROGRESS,
+ CHECK_SUCCEEDED,
+ CHECK_FAILED
+};
+
+typedef struct endpoint_pair_t endpoint_pair_t;
+
+/**
+ * An entry in the check list.
+ */
+struct endpoint_pair_t {
+ /** pair id */
+ u_int32_t id;
+
+ /** priority */
+ u_int64_t priority;
+
+ /** local endpoint */
+ host_t *local;
+
+ /** remote endpoint */
+ host_t *remote;
+
+ /** state */
+ check_state_t state;
+
+ /** number of retransmissions */
+ u_int32_t retransmitted;
+
+ /** the generated packet */
+ packet_t *packet;
+};
+
+/**
+ * Destroys an endpoint pair
+ */
+static void endpoint_pair_destroy(endpoint_pair_t *this)
+{
+ DESTROY_IF(this->local);
+ DESTROY_IF(this->remote);
+ DESTROY_IF(this->packet);
+ free(this);
+}
+
+/**
+ * Creates a new entry for the list.
+ */
+static endpoint_pair_t *endpoint_pair_create(endpoint_notify_t *initiator,
+ endpoint_notify_t *responder, bool initiator_is_local)
+{
+ endpoint_pair_t *this = malloc_thing(endpoint_pair_t);
+
+ this->id = 0;
+
+ u_int32_t pi = initiator->get_priority(initiator);
+ u_int32_t pr = responder->get_priority(responder);
+ this->priority = pow(2, 32) * min(pi, pr) + 2 * max(pi, pr) + (pi > pr ? 1 : 0);
+
+ this->local = initiator_is_local ? initiator->get_base(initiator)
+ : responder->get_base(responder);
+ this->local = this->local->clone(this->local);
+ this->remote = initiator_is_local ? responder->get_host(responder)
+ : initiator->get_host(initiator);
+ this->remote = this->remote->clone(this->remote);
+
+ this->state = CHECK_WAITING;
+ this->retransmitted = 0;
+ this->packet = NULL;
+
+ return this;
+}
+
+
+typedef struct check_list_t check_list_t;
+
+/**
+ * An entry in the linked list.
+ */
+struct check_list_t {
+
+ struct {
+ /** initiator's id */
+ identification_t *id;
+
+ /** initiator's key */
+ chunk_t key;
+
+ /** initiator's endpoints */
+ linked_list_t *endpoints;
+ } initiator;
+
+ struct {
+ /** responder's id */
+ identification_t *id;
+
+ /** responder's key */
+ chunk_t key;
+
+ /** responder's endpoints */
+ linked_list_t *endpoints;
+ } responder;
+
+ /** connect id */
+ chunk_t connect_id;
+
+ /** list of endpoint pairs */
+ linked_list_t *pairs;
+
+ /** pairs queued for triggered checks */
+ linked_list_t *triggered;
+
+ /** state */
+ check_state_t state;
+
+ /** TRUE if this is the initiator */
+ bool is_initiator;
+
+ /** TRUE if the initiator is finishing the checks */
+ bool is_finishing;
+
+ /** the current sender job */
+ job_t *sender;
+
+};
+
+/**
+ * Destroys a checklist
+ */
+static void check_list_destroy(check_list_t *this)
+{
+ DESTROY_IF(this->initiator.id);
+ DESTROY_IF(this->responder.id);
+
+ chunk_free(&this->connect_id);
+ chunk_free(&this->initiator.key);
+ chunk_free(&this->responder.key);
+
+ DESTROY_OFFSET_IF(this->initiator.endpoints,
+ offsetof(endpoint_notify_t, destroy));
+ DESTROY_OFFSET_IF(this->responder.endpoints,
+ offsetof(endpoint_notify_t, destroy));
+
+ DESTROY_FUNCTION_IF(this->pairs, (void*)endpoint_pair_destroy);
+ /* this list contains some of the elements contained in this->pairs */
+ DESTROY_IF(this->triggered);
+
+ free(this);
+}
+
+/**
+ * Creates a new checklist
+ */
+static check_list_t *check_list_create(identification_t *initiator,
+ identification_t *responder,
+ chunk_t connect_id,
+ chunk_t initiator_key,
+ linked_list_t *initiator_endpoints,
+ bool is_initiator)
+{
+ check_list_t *this = malloc_thing(check_list_t);
+
+ this->connect_id = chunk_clone(connect_id);
+
+ this->initiator.id = initiator->clone(initiator);
+ this->initiator.key = chunk_clone(initiator_key);
+ this->initiator.endpoints = initiator_endpoints->clone_offset(initiator_endpoints, offsetof(endpoint_notify_t, clone));
+
+ this->responder.id = responder->clone(responder);
+ this->responder.key = chunk_empty;
+ this->responder.endpoints = NULL;
+
+ this->pairs = linked_list_create();
+ this->triggered = linked_list_create();
+ this->state = CHECK_NONE;
+ this->is_initiator = is_initiator;
+ this->is_finishing = FALSE;
+
+ return this;
+}
+
+typedef struct initiated_t initiated_t;
+
+/**
+ * For an initiator, the data stored about initiated mediation connections
+ */
+struct initiated_t {
+ /** my id */
+ identification_t *id;
+
+ /** peer id */
+ identification_t *peer_id;
+
+ /** list of mediated sas */
+ linked_list_t *mediated;
+};
+
+/**
+ * Destroys a queued initiation
+ */
+static void initiated_destroy(initiated_t *this)
+{
+ DESTROY_IF(this->id);
+ DESTROY_IF(this->peer_id);
+ this->mediated->destroy_offset(this->mediated,
+ offsetof(ike_sa_id_t, destroy));
+ free(this);
+}
+
+/**
+ * Creates a queued initiation
+ */
+static initiated_t *initiated_create(identification_t *id,
+ identification_t *peer_id)
+{
+ initiated_t *this = malloc_thing(initiated_t);
+
+ this->id = id->clone(id);
+ this->peer_id = peer_id->clone(peer_id);
+ this->mediated = linked_list_create();
+
+ return this;
+}
+
+
+typedef struct check_t check_t;
+
+/**
+ * Data exchanged in a connectivity check
+ */
+struct check_t {
+ /** message id */
+ u_int32_t mid;
+
+ /** source of the connectivity check */
+ host_t *src;
+
+ /** destination of the connectivity check */
+ host_t *dst;
+
+ /** connect id */
+ chunk_t connect_id;
+
+ /** endpoint */
+ endpoint_notify_t *endpoint;
+
+ /** raw endpoint payload (to verify the signature) */
+ chunk_t endpoint_raw;
+
+ /** connect auth */
+ chunk_t auth;
+};
+
+/**
+ * Destroys a connectivity check
+ */
+static void check_destroy(check_t *this)
+{
+ chunk_free(&this->connect_id);
+ chunk_free(&this->endpoint_raw);
+ chunk_free(&this->auth);
+ DESTROY_IF(this->src);
+ DESTROY_IF(this->dst);
+ DESTROY_IF(this->endpoint);
+ free(this);
+}
+
+/**
+ * Creates a new connectivity check
+ */
+static check_t *check_create()
+{
+ check_t *this = malloc_thing(check_t);
+
+ this->connect_id = chunk_empty;
+ this->auth = chunk_empty;
+ this->endpoint_raw = chunk_empty;
+ this->src = NULL;
+ this->dst = NULL;
+ this->endpoint = NULL;
+
+ this->mid = 0;
+
+ return this;
+}
+
+typedef struct callback_data_t callback_data_t;
+
+/**
+ * Data required by several callback jobs used in this file
+ */
+struct callback_data_t {
+ /** connect manager */
+ private_connect_manager_t *connect_manager;
+
+ /** connect id */
+ chunk_t connect_id;
+
+ /** message (pair) id */
+ u_int32_t mid;
+};
+
+/**
+ * Destroys a callback data object
+ */
+static void callback_data_destroy(callback_data_t *this)
+{
+ chunk_free(&this->connect_id);
+ free(this);
+}
+
+/**
+ * Creates a new callback data object
+ */
+static callback_data_t *callback_data_create(private_connect_manager_t *connect_manager,
+ chunk_t connect_id)
+{
+ callback_data_t *this = malloc_thing(callback_data_t);
+ this->connect_manager = connect_manager;
+ this->connect_id = chunk_clone(connect_id);
+ this->mid = 0;
+ return this;
+}
+
+/**
+ * Creates a new retransmission data object
+ */
+static callback_data_t *retransmit_data_create(private_connect_manager_t *connect_manager,
+ chunk_t connect_id, u_int32_t mid)
+{
+ callback_data_t *this = callback_data_create(connect_manager, connect_id);
+ this->mid = mid;
+ return this;
+}
+
+typedef struct initiate_data_t initiate_data_t;
+
+/**
+ * Data required by the initiate mediated
+ */
+struct initiate_data_t {
+ /** checklist */
+ check_list_t *checklist;
+
+ /** waiting mediated connections */
+ initiated_t *initiated;
+};
+
+/**
+ * Destroys a initiate data object
+ */
+static void initiate_data_destroy(initiate_data_t *this)
+{
+ check_list_destroy(this->checklist);
+ initiated_destroy(this->initiated);
+ free(this);
+}
+
+/**
+ * Creates a new initiate data object
+ */
+static initiate_data_t *initiate_data_create(check_list_t *checklist,
+ initiated_t *initiated)
+{
+ initiate_data_t *this = malloc_thing(initiate_data_t);
+
+ this->checklist = checklist;
+ this->initiated = initiated;
+
+ return this;
+}
+
+/**
+ * Find an initiated connection by the peers' ids
+ */
+static bool match_initiated_by_ids(initiated_t *current, identification_t *id,
+ identification_t *peer_id)
+{
+ return id->equals(id, current->id) && peer_id->equals(peer_id, current->peer_id);
+}
+
+static status_t get_initiated_by_ids(private_connect_manager_t *this,
+ identification_t *id,
+ identification_t *peer_id,
+ initiated_t **initiated)
+{
+ return this->initiated->find_first(this->initiated,
+ (linked_list_match_t)match_initiated_by_ids,
+ (void**)initiated, id, peer_id);
+}
+
+/**
+ * Removes data about initiated connections
+ */
+static void remove_initiated(private_connect_manager_t *this,
+ initiated_t *initiated)
+{
+ iterator_t *iterator;
+ initiated_t *current;
+
+ iterator = this->initiated->create_iterator(this->initiated, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current == initiated)
+ {
+ iterator->remove(iterator);
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Find the checklist with a specific connect ID
+ */
+static bool match_checklist_by_id(check_list_t *current, chunk_t *connect_id)
+{
+ return chunk_equals(*connect_id, current->connect_id);
+}
+
+static status_t get_checklist_by_id(private_connect_manager_t *this,
+ chunk_t connect_id,
+ check_list_t **check_list)
+{
+ return this->checklists->find_first(this->checklists,
+ (linked_list_match_t)match_checklist_by_id,
+ (void**)check_list, &connect_id);
+}
+
+/**
+ * Removes a checklist
+ */
+static void remove_checklist(private_connect_manager_t *this,
+ check_list_t *checklist)
+{
+ iterator_t *iterator;
+ check_list_t *current;
+
+ iterator = this->checklists->create_iterator(this->checklists, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current == checklist)
+ {
+ iterator->remove(iterator);
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Checks if a list of endpoint_notify_t contains a certain host_t
+ */
+static bool match_endpoint_by_host(endpoint_notify_t *current, host_t *host)
+{
+ return host->equals(host, current->get_host(current));
+}
+
+static status_t endpoints_contain(linked_list_t *endpoints, host_t *host,
+ endpoint_notify_t **endpoint)
+{
+ return endpoints->find_first(endpoints,
+ (linked_list_match_t)match_endpoint_by_host,
+ (void**)endpoint, host);
+}
+
+/**
+ * Inserts an endpoint pair into a list of pairs ordered by priority (high to low)
+ */
+static void insert_pair_by_priority(linked_list_t *pairs, endpoint_pair_t *pair)
+{
+ iterator_t *iterator;
+ endpoint_pair_t *current;
+ bool inserted = FALSE;
+
+ iterator = pairs->create_iterator(pairs, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current->priority < pair->priority)
+ {
+ iterator->insert_before(iterator, pair);
+ inserted = TRUE;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (!inserted)
+ {
+ pairs->insert_last(pairs, pair);
+ }
+}
+
+/**
+ * Searches a list of endpoint_pair_t for a pair with specific host_ts
+ */
+static bool match_pair_by_hosts(endpoint_pair_t *current, host_t *local,
+ host_t *remote)
+{
+ return local->equals(local, current->local) && remote->equals(remote, current->remote);
+}
+
+static status_t get_pair_by_hosts(linked_list_t *pairs, host_t *local,
+ host_t *remote, endpoint_pair_t **pair)
+{
+ return pairs->find_first(pairs, (linked_list_match_t)match_pair_by_hosts,
+ (void**)pair, local, remote);
+}
+
+static bool match_pair_by_id(endpoint_pair_t *current, u_int32_t *id)
+{
+ return current->id == *id;
+}
+
+/**
+ * Searches for a pair with a specific id
+ */
+static status_t get_pair_by_id(check_list_t *checklist, u_int32_t id,
+ endpoint_pair_t **pair)
+{
+ return checklist->pairs->find_first(checklist->pairs,
+ (linked_list_match_t)match_pair_by_id,
+ (void**)pair, &id);
+}
+
+static bool match_succeeded_pair(endpoint_pair_t *current)
+{
+ return current->state == CHECK_SUCCEEDED;
+}
+
+/**
+ * Returns the best pair of state CHECK_SUCCEEDED from a checklist.
+ */
+static status_t get_best_valid_pair(check_list_t *checklist,
+ endpoint_pair_t **pair)
+{
+ return checklist->pairs->find_first(checklist->pairs,
+ (linked_list_match_t)match_succeeded_pair,
+ (void**)pair);
+}
+
+static bool match_waiting_pair(endpoint_pair_t *current)
+{
+ return current->state == CHECK_WAITING;
+}
+
+/**
+ * Returns and *removes* the first triggered pair in state CHECK_WAITING.
+ */
+static status_t get_triggered_pair(check_list_t *checklist,
+ endpoint_pair_t **pair)
+{
+ iterator_t *iterator;
+ endpoint_pair_t *current;
+ status_t status = NOT_FOUND;
+
+ iterator = checklist->triggered->create_iterator(checklist->triggered, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ iterator->remove(iterator);
+
+ if (current->state == CHECK_WAITING)
+ {
+ if (pair)
+ {
+ *pair = current;
+ }
+ status = SUCCESS;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return status;
+}
+
+/**
+ * Prints all the pairs on a checklist
+ */
+static void print_checklist(check_list_t *checklist)
+{
+ iterator_t *iterator;
+ endpoint_pair_t *current;
+
+ DBG1(DBG_IKE, "pairs on checklist %#B:", &checklist->connect_id);
+ iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ DBG1(DBG_IKE, " * %#H - %#H (%d)", current->local, current->remote,
+ current->priority);
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Prunes identical pairs with lower priority from the list
+ * Note: this function also numbers the remaining pairs serially
+ */
+static void prune_pairs(linked_list_t *pairs)
+{
+ iterator_t *iterator, *search;
+ endpoint_pair_t *current, *other;
+ u_int32_t id = 0;
+
+ iterator = pairs->create_iterator(pairs, TRUE);
+ search = pairs->create_iterator(pairs, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ current->id = ++id;
+
+ while (search->iterate(search, (void**)&other))
+ {
+ if (current == other)
+ {
+ continue;
+ }
+
+ if (current->local->equals(current->local, other->local) &&
+ current->remote->equals(current->remote, other->remote))
+ {
+ /* since the list of pairs is sorted by priority in descending
+ * order, and we iterate the list from the beginning, we are
+ * sure that the priority of 'other' is lower than that of
+ * 'current', remove it */
+ DBG1(DBG_IKE, "pruning endpoint pair %#H - %#H with priority %d",
+ other->local, other->remote, other->priority);
+ search->remove(search);
+ endpoint_pair_destroy(other);
+ }
+ }
+ search->reset(search);
+ }
+ search->destroy(search);
+ iterator->destroy(iterator);
+}
+
+/**
+ * Builds a list of endpoint pairs
+ */
+static void build_pairs(check_list_t *checklist)
+{
+ /* FIXME: limit endpoints and pairs */
+ iterator_t *iterator_i, *iterator_r;
+ endpoint_notify_t *initiator, *responder;
+
+ iterator_i = checklist->initiator.endpoints->create_iterator(
+ checklist->initiator.endpoints, TRUE);
+ while (iterator_i->iterate(iterator_i, (void**)&initiator))
+ {
+ iterator_r = checklist->responder.endpoints->create_iterator(
+ checklist->responder.endpoints, TRUE);
+ while (iterator_r->iterate(iterator_r, (void**)&responder))
+ {
+ if (initiator->get_family(initiator) != responder->get_family(responder))
+ {
+ continue;
+ }
+
+ insert_pair_by_priority(checklist->pairs, endpoint_pair_create(
+ initiator, responder, checklist->is_initiator));
+ }
+ iterator_r->destroy(iterator_r);
+ }
+ iterator_i->destroy(iterator_i);
+
+ print_checklist(checklist);
+
+ prune_pairs(checklist->pairs);
+}
+
+/**
+ * Processes the payloads of a connectivity check and returns the extracted data
+ */
+static status_t process_payloads(message_t *message, check_t *check)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != NOTIFY)
+ {
+ DBG1(DBG_IKE, "ignoring payload of type '%N' while processing "
+ "connectivity check", payload_type_names,
+ payload->get_type(payload));
+ continue;
+ }
+
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ switch (notify->get_notify_type(notify))
+ {
+ case ME_ENDPOINT:
+ {
+ if (check->endpoint)
+ {
+ DBG1(DBG_IKE, "connectivity check contains multiple "
+ "ME_ENDPOINT notifies");
+ break;
+ }
+
+ endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify);
+ if (!endpoint)
+ {
+ DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify");
+ break;
+ }
+ check->endpoint = endpoint;
+ check->endpoint_raw = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_ENDPOINT notify");
+ break;
+ }
+ case ME_CONNECTID:
+ {
+ if (check->connect_id.ptr)
+ {
+ DBG1(DBG_IKE, "connectivity check contains multiple "
+ "ME_CONNECTID notifies");
+ break;
+ }
+ check->connect_id = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &check->connect_id);
+ break;
+ }
+ case ME_CONNECTAUTH:
+ {
+ if (check->auth.ptr)
+ {
+ DBG1(DBG_IKE, "connectivity check contains multiple "
+ "ME_CONNECTAUTH notifies");
+ break;
+ }
+ check->auth = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTAUTH %#B", &check->auth);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!check->connect_id.ptr || !check->endpoint || !check->auth.ptr)
+ {
+ DBG1(DBG_IKE, "at least one required payload was missing from the "
+ "connectivity check");
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Builds the signature for a connectivity check
+ */
+static chunk_t build_signature(private_connect_manager_t *this,
+ check_list_t *checklist, check_t *check, bool outbound)
+{
+ u_int32_t mid;
+ chunk_t mid_chunk, key_chunk, sig_chunk;
+ chunk_t sig_hash;
+
+ mid = htonl(check->mid);
+ mid_chunk = chunk_from_thing(mid);
+
+ key_chunk = (checklist->is_initiator && outbound) || (!checklist->is_initiator && !outbound)
+ ? checklist->initiator.key : checklist->responder.key;
+
+ /* signature = SHA1( MID | ME_CONNECTID | ME_ENDPOINT | ME_CONNECTKEY ) */
+ sig_chunk = chunk_cat("cccc", mid_chunk, check->connect_id,
+ check->endpoint_raw, key_chunk);
+ this->hasher->allocate_hash(this->hasher, sig_chunk, &sig_hash);
+ DBG3(DBG_IKE, "sig_chunk %#B", &sig_chunk);
+ DBG3(DBG_IKE, "sig_hash %#B", &sig_hash);
+
+ chunk_free(&sig_chunk);
+ return sig_hash;
+}
+
+static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair);
+static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time);
+static void finish_checks(private_connect_manager_t *this, check_list_t *checklist);
+
+/**
+ * After one of the initiator's pairs has succeeded we finish the checks without
+ * waiting for all the timeouts
+ */
+static job_requeue_t initiator_finish(callback_data_t *data)
+{
+ private_connect_manager_t *this = data->connect_manager;
+
+ this->mutex->lock(this->mutex);
+
+ check_list_t *checklist;
+ if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found, can't finish "
+ "connectivity checks", &data->connect_id);
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+ }
+
+ finish_checks(this, checklist);
+
+ this->mutex->unlock(this->mutex);
+
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Updates the state of the whole checklist
+ */
+static void update_checklist_state(private_connect_manager_t *this,
+ check_list_t *checklist)
+{
+ iterator_t *iterator;
+ endpoint_pair_t *current;
+ bool in_progress = FALSE, succeeded = FALSE;
+
+ iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ switch(current->state)
+ {
+ case CHECK_WAITING:
+ /* at least one is still waiting -> checklist remains
+ * in waiting state */
+ iterator->destroy(iterator);
+ return;
+ case CHECK_IN_PROGRESS:
+ in_progress = TRUE;
+ break;
+ case CHECK_SUCCEEDED:
+ succeeded = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (checklist->is_initiator && succeeded && !checklist->is_finishing)
+ {
+ /* instead of waiting until all checks have finished (i.e. all
+ * retransmissions have failed) the initiator finishes the checks
+ * right after the first check has succeeded. to allow a probably
+ * better pair to succeed, we still wait a certain time */
+ DBG2(DBG_IKE, "fast finishing checks for checklist '%#B'",
+ &checklist->connect_id);
+
+ callback_data_t *data = callback_data_create(this, checklist->connect_id);
+ job_t *job = (job_t*)callback_job_create((callback_job_cb_t)initiator_finish, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
+ charon->scheduler->schedule_job_ms(charon->scheduler, job, ME_WAIT_TO_FINISH);
+ checklist->is_finishing = TRUE;
+ }
+
+ if (in_progress)
+ {
+ checklist->state = CHECK_IN_PROGRESS;
+ }
+ else if (succeeded)
+ {
+ checklist->state = CHECK_SUCCEEDED;
+ }
+ else
+ {
+ checklist->state = CHECK_FAILED;
+ }
+}
+
+/**
+ * This function is triggered for each sent check after a specific timeout
+ */
+static job_requeue_t retransmit(callback_data_t *data)
+{
+ private_connect_manager_t *this = data->connect_manager;
+
+ this->mutex->lock(this->mutex);
+
+ check_list_t *checklist;
+ if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found, can't retransmit "
+ "connectivity check", &data->connect_id);
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+ }
+
+ endpoint_pair_t *pair;
+ if (get_pair_by_id(checklist, data->mid, &pair) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "pair with id '%d' not found, can't retransmit "
+ "connectivity check", data->mid);
+ goto retransmit_end;
+ }
+
+ if (pair->state != CHECK_IN_PROGRESS)
+ {
+ DBG2(DBG_IKE, "pair with id '%d' is in wrong state [%d], don't "
+ "retransmit the connectivity check", data->mid, pair->state);
+ goto retransmit_end;
+ }
+
+ if (++pair->retransmitted > ME_MAX_RETRANS)
+ {
+ DBG2(DBG_IKE, "pair with id '%d' failed after %d retransmissions",
+ data->mid, ME_MAX_RETRANS);
+ pair->state = CHECK_FAILED;
+ goto retransmit_end;
+ }
+
+ charon->sender->send(charon->sender, pair->packet->clone(pair->packet));
+
+ queue_retransmission(this, checklist, pair);
+
+retransmit_end:
+ update_checklist_state(this, checklist);
+
+ switch(checklist->state)
+ {
+ case CHECK_SUCCEEDED:
+ case CHECK_FAILED:
+ finish_checks(this, checklist);
+ break;
+ default:
+ break;
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ /* we reschedule it manually */
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Queues a retransmission job
+ */
+static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair)
+{
+ callback_data_t *data = retransmit_data_create(this, checklist->connect_id, pair->id);
+ job_t *job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
+
+ u_int32_t retransmission = pair->retransmitted + 1;
+ u_int32_t rto = ME_INTERVAL;
+ if (retransmission > ME_BOOST)
+ {
+ rto = (u_int32_t)(ME_INTERVAL * pow(ME_RETRANS_BASE, retransmission - ME_BOOST));
+ }
+ DBG2(DBG_IKE, "scheduling retransmission %d of pair '%d' in %dms",
+ retransmission, pair->id, rto);
+
+ charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)job, rto);
+}
+
+/**
+ * Sends a check
+ */
+static void send_check(private_connect_manager_t *this, check_list_t *checklist,
+ check_t *check, endpoint_pair_t *pair, bool request)
+{
+ message_t *message = message_create();
+ message->set_message_id(message, check->mid);
+ message->set_exchange_type(message, INFORMATIONAL);
+ message->set_request(message, request);
+ message->set_destination(message, check->dst->clone(check->dst));
+ message->set_source(message, check->src->clone(check->src));
+
+ ike_sa_id_t *ike_sa_id = ike_sa_id_create(0, 0, request);
+ message->set_ike_sa_id(message, ike_sa_id);
+ ike_sa_id->destroy(ike_sa_id);
+
+ message->add_notify(message, FALSE, ME_CONNECTID, check->connect_id);
+ DBG2(DBG_IKE, "send ME_CONNECTID %#B", &check->connect_id);
+
+ notify_payload_t *endpoint = check->endpoint->build_notify(check->endpoint);
+ check->endpoint_raw = chunk_clone(endpoint->get_notification_data(endpoint));
+ message->add_payload(message, (payload_t*)endpoint);
+ DBG2(DBG_IKE, "send ME_ENDPOINT notify");
+
+ check->auth = build_signature(this, checklist, check, TRUE);
+ message->add_notify(message, FALSE, ME_CONNECTAUTH, check->auth);
+ DBG2(DBG_IKE, "send ME_CONNECTAUTH %#B", &check->auth);
+
+ packet_t *packet;
+ if (message->generate(message, NULL, NULL, &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet->clone(packet));
+
+ if (request)
+ {
+ DESTROY_IF(pair->packet);
+ pair->packet = packet;
+ pair->retransmitted = 0;
+ queue_retransmission(this, checklist, pair);
+ }
+ else
+ {
+ packet->destroy(packet);
+ }
+ }
+ message->destroy(message);
+}
+
+/**
+ * Queues a triggered check
+ */
+static void queue_triggered_check(private_connect_manager_t *this,
+ check_list_t *checklist, endpoint_pair_t *pair)
+{
+ DBG2(DBG_IKE, "queueing triggered check for pair '%d'", pair->id);
+ pair->state = CHECK_WAITING;
+ checklist->triggered->insert_last(checklist->triggered, pair);
+
+ if (!checklist->sender)
+ {
+ /* if the sender is not running we restart it */
+ schedule_checks(this, checklist, ME_INTERVAL);
+ }
+}
+
+/**
+ * This function is triggered for each checklist at a specific interval
+ */
+static job_requeue_t sender(callback_data_t *data)
+{
+ private_connect_manager_t *this = data->connect_manager;
+
+ this->mutex->lock(this->mutex);
+
+ check_list_t *checklist;
+ if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found, can't send "
+ "connectivity check", &data->connect_id);
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+ }
+
+ /* reset the sender */
+ checklist->sender = NULL;
+
+ endpoint_pair_t *pair;
+ if (get_triggered_pair(checklist, &pair) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "no triggered check queued, sending an ordinary check");
+
+ if (checklist->pairs->find_first(checklist->pairs,
+ (linked_list_match_t)match_waiting_pair,
+ (void**)&pair) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_IKE, "no pairs in waiting state, aborting");
+ return JOB_REQUEUE_NONE;
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "triggered check found");
+ }
+
+ check_t *check = check_create();
+ check->mid = pair->id;
+ check->src = pair->local->clone(pair->local);
+ check->dst = pair->remote->clone(pair->remote);
+ check->connect_id = chunk_clone(checklist->connect_id);
+ check->endpoint = endpoint_notify_create_from_host(PEER_REFLEXIVE, NULL,
+ NULL);
+
+ pair->state = CHECK_IN_PROGRESS;
+
+ send_check(this, checklist, check, pair, TRUE);
+
+ check_destroy(check);
+
+ /* schedule this job again */
+ schedule_checks(this, checklist, ME_INTERVAL);
+
+ this->mutex->unlock(this->mutex);
+
+ /* we reschedule it manually */
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedules checks for a checklist (time in ms)
+ */
+static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time)
+{
+ callback_data_t *data = callback_data_create(this, checklist->connect_id);
+ checklist->sender = (job_t*)callback_job_create((callback_job_cb_t)sender, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
+ charon->scheduler->schedule_job_ms(charon->scheduler, checklist->sender, time);
+}
+
+/**
+ * Initiates waiting mediated connections
+ */
+static job_requeue_t initiate_mediated(initiate_data_t *data)
+{
+ check_list_t *checklist = data->checklist;
+ initiated_t *initiated = data->initiated;
+
+ endpoint_pair_t *pair;
+ if (get_best_valid_pair(checklist, &pair) == SUCCESS)
+ {
+ ike_sa_id_t *waiting_sa;
+ iterator_t *iterator = initiated->mediated->create_iterator(initiated->mediated, TRUE);
+ while (iterator->iterate(iterator, (void**)&waiting_sa))
+ {
+ ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa);
+ if (sa->initiate_mediated(sa, pair->local, pair->remote, checklist->connect_id) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "establishing mediated connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
+ }
+ iterator->destroy(iterator);
+ }
+ else
+ {
+ /* this should (can?) not happen */
+ }
+
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Finishes checks for a checklist
+ */
+static void finish_checks(private_connect_manager_t *this, check_list_t *checklist)
+{
+ if (checklist->is_initiator)
+ {
+ initiated_t *initiated;
+ if (get_initiated_by_ids(this, checklist->initiator.id,
+ checklist->responder.id, &initiated) == SUCCESS)
+ {
+ remove_checklist(this, checklist);
+ remove_initiated(this, initiated);
+
+ initiate_data_t *data = initiate_data_create(checklist, initiated);
+ job_t *job = (job_t*)callback_job_create((callback_job_cb_t)initiate_mediated, data, (callback_job_cleanup_t)initiate_data_destroy, NULL);
+ charon->processor->queue_job(charon->processor, job);
+ return;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "there is no mediated connection waiting between '%Y'"
+ " and '%Y'", checklist->initiator.id, checklist->responder.id);
+ }
+ }
+}
+
+/**
+ * Process the response to one of our requests
+ */
+static void process_response(private_connect_manager_t *this, check_t *check,
+ check_list_t *checklist)
+{
+ endpoint_pair_t *pair;
+ if (get_pair_by_id(checklist, check->mid, &pair) == SUCCESS)
+ {
+ if (pair->local->equals(pair->local, check->dst) &&
+ pair->remote->equals(pair->remote, check->src))
+ {
+ DBG1(DBG_IKE, "endpoint pair '%d' is valid: '%#H' - '%#H'",
+ pair->id, pair->local, pair->remote);
+ pair->state = CHECK_SUCCEEDED;
+ }
+
+ linked_list_t *local_endpoints = checklist->is_initiator ?
+ checklist->initiator.endpoints : checklist->responder.endpoints;
+
+ endpoint_notify_t *local_endpoint;
+ if (endpoints_contain(local_endpoints,
+ check->endpoint->get_host(check->endpoint),
+ &local_endpoint) != SUCCESS)
+ {
+ local_endpoint = endpoint_notify_create_from_host(PEER_REFLEXIVE,
+ check->endpoint->get_host(check->endpoint), pair->local);
+ local_endpoint->set_priority(local_endpoint,
+ check->endpoint->get_priority(check->endpoint));
+ local_endpoints->insert_last(local_endpoints, local_endpoint);
+ }
+
+ update_checklist_state(this, checklist);
+
+ switch(checklist->state)
+ {
+ case CHECK_SUCCEEDED:
+ case CHECK_FAILED:
+ finish_checks(this, checklist);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "pair with id '%d' not found", check->mid);
+ }
+}
+
+static void process_request(private_connect_manager_t *this, check_t *check,
+ check_list_t *checklist)
+{
+ linked_list_t *remote_endpoints = checklist->is_initiator ?
+ checklist->responder.endpoints : checklist->initiator.endpoints;
+
+ endpoint_notify_t *peer_reflexive, *remote_endpoint;
+ peer_reflexive = endpoint_notify_create_from_host(PEER_REFLEXIVE,
+ check->src, NULL);
+ peer_reflexive->set_priority(peer_reflexive,
+ check->endpoint->get_priority(check->endpoint));
+
+ if (endpoints_contain(remote_endpoints, check->src, &remote_endpoint) != SUCCESS)
+ {
+ remote_endpoint = peer_reflexive->clone(peer_reflexive);
+ remote_endpoints->insert_last(remote_endpoints, remote_endpoint);
+ }
+
+ endpoint_pair_t *pair;
+ if (get_pair_by_hosts(checklist->pairs, check->dst, check->src,
+ &pair) == SUCCESS)
+ {
+ switch(pair->state)
+ {
+ case CHECK_IN_PROGRESS:
+ /* prevent retransmissions */
+ pair->retransmitted = ME_MAX_RETRANS;
+ /* FIXME: we should wait to the next rto to send the triggered
+ * check */
+ /* fall-through */
+ case CHECK_WAITING:
+ case CHECK_FAILED:
+ queue_triggered_check(this, checklist, pair);
+ break;
+ case CHECK_SUCCEEDED:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ endpoint_notify_t *local_endpoint = endpoint_notify_create_from_host(HOST, check->dst, NULL);
+
+ endpoint_notify_t *initiator = checklist->is_initiator ? local_endpoint : remote_endpoint;
+ endpoint_notify_t *responder = checklist->is_initiator ? remote_endpoint : local_endpoint;
+
+ pair = endpoint_pair_create(initiator, responder, checklist->is_initiator);
+ pair->id = checklist->pairs->get_count(checklist->pairs) + 1;
+
+ insert_pair_by_priority(checklist->pairs, pair);
+
+ queue_triggered_check(this, checklist, pair);
+
+ local_endpoint->destroy(local_endpoint);
+ }
+
+ check_t *response = check_create();
+
+ response->mid = check->mid;
+ response->src = check->dst->clone(check->dst);
+ response->dst = check->src->clone(check->src);
+ response->connect_id = chunk_clone(check->connect_id);
+ response->endpoint = peer_reflexive;
+
+ send_check(this, checklist, response, pair, FALSE);
+
+ check_destroy(response);
+}
+
+/**
+ * Implementation of connect_manager_t.process_check.
+ */
+static void process_check(private_connect_manager_t *this, message_t *message)
+{
+ if (message->parse_body(message, NULL, NULL) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
+ exchange_type_names, message->get_exchange_type(message),
+ message->get_request(message) ? "request" : "response",
+ message->get_message_id(message));
+ return;
+ }
+
+ check_t *check = check_create();
+ check->mid = message->get_message_id(message);
+ check->src = message->get_source(message);
+ check->src = check->src->clone(check->src);
+ check->dst = message->get_destination(message);
+ check->dst = check->dst->clone(check->dst);
+
+ if (process_payloads(message, check) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "invalid connectivity check %s received",
+ message->get_request(message) ? "request" : "response");
+ check_destroy(check);
+ return;
+ }
+
+ this->mutex->lock(this->mutex);
+
+ check_list_t *checklist;
+ if (get_checklist_by_id(this, check->connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found",
+ &check->connect_id);
+ check_destroy(check);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+
+ chunk_t sig = build_signature(this, checklist, check, FALSE);
+ if (!chunk_equals(sig, check->auth))
+ {
+ DBG1(DBG_IKE, "connectivity check verification failed");
+ check_destroy(check);
+ chunk_free(&sig);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+ chunk_free(&sig);
+
+ if (message->get_request(message))
+ {
+ process_request(this, check, checklist);
+ }
+ else
+ {
+ process_response(this, check, checklist);
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ check_destroy(check);
+}
+
+/**
+ * Implementation of connect_manager_t.check_and_register.
+ */
+static bool check_and_register(private_connect_manager_t *this,
+ identification_t *id, identification_t *peer_id,
+ ike_sa_id_t *mediated_sa)
+{
+ initiated_t *initiated;
+ bool already_there = TRUE;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
+ {
+ DBG2(DBG_IKE, "registered waiting mediated connection with '%Y'",
+ peer_id);
+ initiated = initiated_create(id, peer_id);
+ this->initiated->insert_last(this->initiated, initiated);
+ already_there = FALSE;
+ }
+
+ if (initiated->mediated->find_first(initiated->mediated,
+ (linked_list_match_t)mediated_sa->equals,
+ NULL, mediated_sa) != SUCCESS)
+ {
+ initiated->mediated->insert_last(initiated->mediated,
+ mediated_sa->clone(mediated_sa));
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ return already_there;
+}
+
+/**
+ * Implementation of connect_manager_t.check_and_initiate.
+ */
+static void check_and_initiate(private_connect_manager_t *this,
+ ike_sa_id_t *mediation_sa, identification_t *id,
+ identification_t *peer_id)
+{
+ initiated_t *initiated;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
+ {
+ DBG2(DBG_IKE, "no waiting mediated connections with '%Y'", peer_id);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+
+ ike_sa_id_t *waiting_sa;
+ iterator_t *iterator = initiated->mediated->create_iterator(
+ initiated->mediated, TRUE);
+ while (iterator->iterate(iterator, (void**)&waiting_sa))
+ {
+ job_t *job = (job_t*)reinitiate_mediation_job_create(mediation_sa,
+ waiting_sa);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ iterator->destroy(iterator);
+
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of connect_manager_t.set_initiator_data.
+ */
+static status_t set_initiator_data(private_connect_manager_t *this,
+ identification_t *initiator,
+ identification_t *responder,
+ chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints, bool is_initiator)
+{
+ check_list_t *checklist;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_checklist_by_id(this, connect_id, NULL) == SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' already exists, aborting",
+ &connect_id);
+ this->mutex->unlock(this->mutex);
+ return FAILED;
+ }
+
+ checklist = check_list_create(initiator, responder, connect_id, key,
+ endpoints, is_initiator);
+ this->checklists->insert_last(this->checklists, checklist);
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of connect_manager_t.set_responder_data.
+ */
+static status_t set_responder_data(private_connect_manager_t *this,
+ chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints)
+{
+ check_list_t *checklist;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found",
+ &connect_id);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+
+ checklist->responder.key = chunk_clone(key);
+ checklist->responder.endpoints = endpoints->clone_offset(endpoints,
+ offsetof(endpoint_notify_t, clone));
+ checklist->state = CHECK_WAITING;
+
+ build_pairs(checklist);
+
+ /* send the first check immediately */
+ schedule_checks(this, checklist, 0);
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of connect_manager_t.stop_checks.
+ */
+static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
+{
+ check_list_t *checklist;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%#B' not found",
+ &connect_id);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+
+ DBG1(DBG_IKE, "removing checklist with id '%#B'", &connect_id);
+
+ remove_checklist(this, checklist);
+ check_list_destroy(checklist);
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of connect_manager_t.destroy.
+ */
+static void destroy(private_connect_manager_t *this)
+{
+ this->mutex->lock(this->mutex);
+
+ this->hasher->destroy(this->hasher);
+ this->checklists->destroy_function(this->checklists, (void*)check_list_destroy);
+ this->initiated->destroy_function(this->initiated, (void*)initiated_destroy);
+
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+connect_manager_t *connect_manager_create()
+{
+ private_connect_manager_t *this = malloc_thing(private_connect_manager_t);
+
+ this->public.destroy = (void(*)(connect_manager_t*))destroy;
+ this->public.check_and_register = (bool(*)(connect_manager_t*,identification_t*,identification_t*,ike_sa_id_t*))check_and_register;
+ this->public.check_and_initiate = (void(*)(connect_manager_t*,ike_sa_id_t*,identification_t*,identification_t*))check_and_initiate;
+ this->public.set_initiator_data = (status_t(*)(connect_manager_t*,identification_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))set_initiator_data;
+ this->public.set_responder_data = (status_t(*)(connect_manager_t*,chunk_t,chunk_t,linked_list_t*))set_responder_data;
+ this->public.process_check = (void(*)(connect_manager_t*,message_t*))process_check;
+ this->public.stop_checks = (status_t(*)(connect_manager_t*,chunk_t))stop_checks;
+
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to create connect manager, SHA1 not supported");
+ free(this);
+ return NULL;
+ }
+
+ this->checklists = linked_list_create();
+ this->initiated = linked_list_create();
+
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ return (connect_manager_t*)this;
+}
diff --git a/src/libcharon/sa/connect_manager.h b/src/libcharon/sa/connect_manager.h
new file mode 100644
index 000000000..8fa8ff697
--- /dev/null
+++ b/src/libcharon/sa/connect_manager.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007-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 connect_manager connect_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef CONNECT_MANAGER_H_
+#define CONNECT_MANAGER_H_
+
+typedef struct connect_manager_t connect_manager_t;
+
+#include <encoding/message.h>
+#include <sa/ike_sa_id.h>
+#include <utils/identification.h>
+
+/**
+ * The connection manager is responsible for establishing a direct
+ * connection with another peer.
+ */
+struct connect_manager_t {
+
+ /**
+ * Checks if a there is already a mediated connection registered
+ * between two peers.
+ *
+ * @param id my id
+ * @param peer_id the other peer's id
+ * @param mediated_sa the IKE_SA ID of the mediated connection
+ * @returns
+ * - TRUE, if a mediated connection is registered
+ * - FALSE, otherwise
+ */
+ bool (*check_and_register) (connect_manager_t *this, identification_t *id,
+ identification_t *peer_id,
+ ike_sa_id_t *mediated_sa);
+
+ /**
+ * Checks if there are waiting connections with a specific peer.
+ * If so, reinitiate them.
+ *
+ * @param id my id
+ * @param peer_id the other peer's id
+ */
+ void (*check_and_initiate) (connect_manager_t *this,
+ ike_sa_id_t *mediation_sa, identification_t *id,
+ identification_t *peer_id);
+
+ /**
+ * Creates a checklist and sets the initiator's data.
+ *
+ * @param initiator ID of the initiator
+ * @param responder ID of the responder
+ * @param connect_id the connect ID provided by the initiator
+ * @param key the initiator's key
+ * @param endpoints the initiator's endpoints
+ * @param is_initiator TRUE, if the caller of this method is the initiator
+ * @returns SUCCESS
+ */
+ status_t (*set_initiator_data) (connect_manager_t *this,
+ identification_t *initiator,
+ identification_t *responder,
+ chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints,
+ bool is_initiator);
+
+ /**
+ * Updates a checklist and sets the responder's data. The checklist's
+ * state is advanced to WAITING which means that checks will be sent.
+ *
+ * @param connect_id the connect ID
+ * @param chunk_t the responder's key
+ * @param endpoints the responder's endpoints
+ * @returns
+ * - NOT_FOUND, if the checklist has not been found
+ * - SUCCESS, otherwise
+ */
+ status_t (*set_responder_data) (connect_manager_t *this,
+ chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints);
+
+ /**
+ * Stops checks for a checklist. Called after the responder received an
+ * IKE_SA_INIT request which contains a ME_CONNECTID payload.
+ *
+ * @param connect_id the connect ID
+ * @returns
+ * - NOT_FOUND, if the checklist has not been found
+ * - SUCCESS, otherwise
+ */
+ status_t (*stop_checks) (connect_manager_t *this, chunk_t connect_id);
+
+ /**
+ * Processes a connectivity check
+ *
+ * @param message the received message
+ */
+ void (*process_check) (connect_manager_t *this, message_t *message);
+
+ /**
+ * Destroys the manager with all data.
+ */
+ void (*destroy) (connect_manager_t *this);
+};
+
+/**
+ * Create a manager.
+ *
+ * @returns connect_manager_t object
+ */
+connect_manager_t *connect_manager_create(void);
+
+#endif /** CONNECT_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
new file mode 100644
index 000000000..023f0749f
--- /dev/null
+++ b/src/libcharon/sa/ike_sa.c
@@ -0,0 +1,2227 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <time.h>
+
+#include "ike_sa.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <hydra.h>
+#include <utils/linked_list.h>
+#include <utils/lexparser.h>
+#include <sa/task_manager.h>
+#include <sa/tasks/ike_init.h>
+#include <sa/tasks/ike_natd.h>
+#include <sa/tasks/ike_mobike.h>
+#include <sa/tasks/ike_auth.h>
+#include <sa/tasks/ike_auth_lifetime.h>
+#include <sa/tasks/ike_config.h>
+#include <sa/tasks/ike_cert_pre.h>
+#include <sa/tasks/ike_cert_post.h>
+#include <sa/tasks/ike_rekey.h>
+#include <sa/tasks/ike_reauth.h>
+#include <sa/tasks/ike_delete.h>
+#include <sa/tasks/ike_dpd.h>
+#include <sa/tasks/ike_vendor.h>
+#include <sa/tasks/child_create.h>
+#include <sa/tasks/child_delete.h>
+#include <sa/tasks/child_rekey.h>
+#include <processing/jobs/retransmit_job.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/send_dpd_job.h>
+#include <processing/jobs/send_keepalive_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+
+#ifdef ME
+#include <sa/tasks/ike_me.h>
+#include <processing/jobs/initiate_mediation_job.h>
+#endif
+
+ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING,
+ "CREATED",
+ "CONNECTING",
+ "ESTABLISHED",
+ "PASSIVE",
+ "REKEYING",
+ "DELETING",
+ "DESTROYING",
+);
+
+typedef struct private_ike_sa_t private_ike_sa_t;
+typedef struct attribute_entry_t attribute_entry_t;
+
+/**
+ * Private data of an ike_sa_t object.
+ */
+struct private_ike_sa_t {
+
+ /**
+ * Public members
+ */
+ ike_sa_t public;
+
+ /**
+ * Identifier for the current IKE_SA.
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * unique numerical ID for this IKE_SA.
+ */
+ u_int32_t unique_id;
+
+ /**
+ * Current state of the IKE_SA
+ */
+ ike_sa_state_t state;
+
+ /**
+ * IKE configuration used to set up this IKE_SA
+ */
+ ike_cfg_t *ike_cfg;
+
+ /**
+ * Peer and authentication information to establish IKE_SA.
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * currently used authentication ruleset, local (as auth_cfg_t)
+ */
+ auth_cfg_t *my_auth;
+
+ /**
+ * list of completed local authentication rounds
+ */
+ linked_list_t *my_auths;
+
+ /**
+ * list of completed remote authentication rounds
+ */
+ linked_list_t *other_auths;
+
+ /**
+ * currently used authentication constraints, remote (as auth_cfg_t)
+ */
+ auth_cfg_t *other_auth;
+
+ /**
+ * Selected IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * Juggles tasks to process messages
+ */
+ task_manager_t *task_manager;
+
+ /**
+ * Address of local host
+ */
+ host_t *my_host;
+
+ /**
+ * Address of remote host
+ */
+ host_t *other_host;
+
+#ifdef ME
+ /**
+ * Are we mediation server
+ */
+ bool is_mediation_server;
+
+ /**
+ * Server reflexive host
+ */
+ host_t *server_reflexive_host;
+
+ /**
+ * Connect ID
+ */
+ chunk_t connect_id;
+#endif /* ME */
+
+ /**
+ * Identification used for us
+ */
+ identification_t *my_id;
+
+ /**
+ * Identification used for other
+ */
+ identification_t *other_id;
+
+ /**
+ * set of extensions the peer supports
+ */
+ ike_extension_t extensions;
+
+ /**
+ * set of condition flags currently enabled for this IKE_SA
+ */
+ ike_condition_t conditions;
+
+ /**
+ * Linked List containing the child sa's of the current IKE_SA.
+ */
+ linked_list_t *child_sas;
+
+ /**
+ * keymat of this IKE_SA
+ */
+ keymat_t *keymat;
+
+ /**
+ * Virtual IP on local host, if any
+ */
+ host_t *my_virtual_ip;
+
+ /**
+ * Virtual IP on remote host, if any
+ */
+ host_t *other_virtual_ip;
+
+ /**
+ * List of configuration attributes (attribute_entry_t)
+ */
+ linked_list_t *attributes;
+
+ /**
+ * list of peers additional addresses, transmitted via MOBIKE
+ */
+ linked_list_t *additional_addresses;
+
+ /**
+ * previously value of received DESTINATION_IP hash
+ */
+ chunk_t nat_detection_dest;
+
+ /**
+ * number pending UPDATE_SA_ADDRESS (MOBIKE)
+ */
+ u_int32_t pending_updates;
+
+ /**
+ * NAT keep alive interval
+ */
+ u_int32_t keepalive_interval;
+
+ /**
+ * Timestamps for this IKE_SA
+ */
+ u_int32_t stats[STAT_MAX];
+
+ /**
+ * how many times we have retried so far (keyingtries)
+ */
+ u_int32_t keyingtry;
+
+ /**
+ * local host address to be used for IKE, set via MIGRATE kernel message
+ */
+ host_t *local_host;
+
+ /**
+ * remote host address to be used for IKE, set via MIGRATE kernel message
+ */
+ host_t *remote_host;
+};
+
+/**
+ * Entry to maintain install configuration attributes during IKE_SA lifetime
+ */
+struct attribute_entry_t {
+ /** handler used to install this attribute */
+ attribute_handler_t *handler;
+ /** attribute type */
+ configuration_attribute_type_t type;
+ /** attribute data */
+ chunk_t data;
+};
+
+/**
+ * get the time of the latest traffic processed by the kernel
+ */
+static time_t get_use_time(private_ike_sa_t* this, bool inbound)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ time_t use_time, current;
+
+ if (inbound)
+ {
+ use_time = this->stats[STAT_INBOUND];
+ }
+ else
+ {
+ use_time = this->stats[STAT_OUTBOUND];
+ }
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ child_sa->get_usestats(child_sa, inbound, &current, NULL);
+ use_time = max(use_time, current);
+ }
+ enumerator->destroy(enumerator);
+
+ return use_time;
+}
+
+/**
+ * Implementation of ike_sa_t.get_unique_id
+ */
+static u_int32_t get_unique_id(private_ike_sa_t *this)
+{
+ return this->unique_id;
+}
+
+/**
+ * Implementation of ike_sa_t.get_name.
+ */
+static char *get_name(private_ike_sa_t *this)
+{
+ if (this->peer_cfg)
+ {
+ return this->peer_cfg->get_name(this->peer_cfg);
+ }
+ return "(unnamed)";
+}
+
+/**
+ * Implementation of ike_sa_t.get_statistic.
+ */
+static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
+{
+ if (kind < STAT_MAX)
+ {
+ return this->stats[kind];
+ }
+ return 0;
+}
+
+/**
+ * Implementation of ike_sa_t.get_my_host.
+ */
+static host_t *get_my_host(private_ike_sa_t *this)
+{
+ return this->my_host;
+}
+
+/**
+ * Implementation of ike_sa_t.set_my_host.
+ */
+static void set_my_host(private_ike_sa_t *this, host_t *me)
+{
+ DESTROY_IF(this->my_host);
+ this->my_host = me;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_host.
+ */
+static host_t *get_other_host(private_ike_sa_t *this)
+{
+ return this->other_host;
+}
+
+/**
+ * Implementation of ike_sa_t.set_other_host.
+ */
+static void set_other_host(private_ike_sa_t *this, host_t *other)
+{
+ DESTROY_IF(this->other_host);
+ this->other_host = other;
+}
+
+/**
+ * Implementation of ike_sa_t.get_peer_cfg
+ */
+static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this)
+{
+ return this->peer_cfg;
+}
+
+/**
+ * Implementation of ike_sa_t.set_peer_cfg
+ */
+static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
+{
+ DESTROY_IF(this->peer_cfg);
+ peer_cfg->get_ref(peer_cfg);
+ this->peer_cfg = peer_cfg;
+
+ if (this->ike_cfg == NULL)
+ {
+ this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+ this->ike_cfg->get_ref(this->ike_cfg);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.get_auth_cfg
+ */
+static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
+{
+ if (local)
+ {
+ return this->my_auth;
+ }
+ return this->other_auth;
+}
+
+/**
+ * Implementation of ike_sa_t.add_auth_cfg
+ */
+static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
+{
+ if (local)
+ {
+ this->my_auths->insert_last(this->my_auths, cfg);
+ }
+ else
+ {
+ this->other_auths->insert_last(this->other_auths, cfg);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.create_auth_cfg_enumerator
+ */
+static enumerator_t* create_auth_cfg_enumerator(private_ike_sa_t *this,
+ bool local)
+{
+ if (local)
+ {
+ return this->my_auths->create_enumerator(this->my_auths);
+ }
+ return this->other_auths->create_enumerator(this->other_auths);
+}
+
+/**
+ * Flush the stored authentication round information
+ */
+static void flush_auth_cfgs(private_ike_sa_t *this)
+{
+ auth_cfg_t *cfg;
+
+ if (lib->settings->get_bool(lib->settings, "charon.flush_auth_cfg", FALSE))
+ {
+ while (this->my_auths->remove_last(this->my_auths,
+ (void**)&cfg) == SUCCESS)
+ {
+ cfg->destroy(cfg);
+ }
+ while (this->other_auths->remove_last(this->other_auths,
+ (void**)&cfg) == SUCCESS)
+ {
+ cfg->destroy(cfg);
+ }
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_ike_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of ike_sa_t.set_proposal
+ */
+static void set_proposal(private_ike_sa_t *this, proposal_t *proposal)
+{
+ DESTROY_IF(this->proposal);
+ this->proposal = proposal->clone(proposal);
+}
+
+/**
+ * Implementation of ike_sa_t.set_message_id
+ */
+static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid)
+{
+ if (initiate)
+ {
+ this->task_manager->reset(this->task_manager, mid, UINT_MAX);
+ }
+ else
+ {
+ this->task_manager->reset(this->task_manager, UINT_MAX, mid);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.send_keepalive
+ */
+static void send_keepalive(private_ike_sa_t *this)
+{
+ send_keepalive_job_t *job;
+ time_t last_out, now, diff;
+
+ if (!(this->conditions & COND_NAT_HERE) || this->keepalive_interval == 0)
+ { /* disable keep alives if we are not NATed anymore */
+ return;
+ }
+
+ last_out = get_use_time(this, FALSE);
+ now = time_monotonic(NULL);
+
+ diff = now - last_out;
+
+ if (diff >= this->keepalive_interval)
+ {
+ packet_t *packet;
+ chunk_t data;
+
+ packet = packet_create();
+ packet->set_source(packet, this->my_host->clone(this->my_host));
+ packet->set_destination(packet, this->other_host->clone(this->other_host));
+ data.ptr = malloc(1);
+ data.ptr[0] = 0xFF;
+ data.len = 1;
+ packet->set_data(packet, data);
+ DBG1(DBG_IKE, "sending keep alive");
+ charon->sender->send(charon->sender, packet);
+ diff = 0;
+ }
+ job = send_keepalive_job_create(this->ike_sa_id);
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)job,
+ this->keepalive_interval - diff);
+}
+
+/**
+ * Implementation of ike_sa_t.get_ike_cfg
+ */
+static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this)
+{
+ return this->ike_cfg;
+}
+
+/**
+ * Implementation of ike_sa_t.set_ike_cfg
+ */
+static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg)
+{
+ ike_cfg->get_ref(ike_cfg);
+ this->ike_cfg = ike_cfg;
+}
+
+/**
+ * Implementation of ike_sa_t.enable_extension.
+ */
+static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
+{
+ this->extensions |= extension;
+}
+
+/**
+ * Implementation of ike_sa_t.has_extension.
+ */
+static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
+{
+ return (this->extensions & extension) != FALSE;
+}
+
+/**
+ * Implementation of ike_sa_t.has_condition.
+ */
+static bool has_condition(private_ike_sa_t *this, ike_condition_t condition)
+{
+ return (this->conditions & condition) != FALSE;
+}
+
+/**
+ * Implementation of ike_sa_t.enable_condition.
+ */
+static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
+ bool enable)
+{
+ if (has_condition(this, condition) != enable)
+ {
+ if (enable)
+ {
+ this->conditions |= condition;
+ switch (condition)
+ {
+ case COND_NAT_HERE:
+ DBG1(DBG_IKE, "local host is behind NAT, sending keep alives");
+ this->conditions |= COND_NAT_ANY;
+ send_keepalive(this);
+ break;
+ case COND_NAT_THERE:
+ DBG1(DBG_IKE, "remote host is behind NAT");
+ this->conditions |= COND_NAT_ANY;
+ break;
+ case COND_NAT_FAKE:
+ DBG1(DBG_IKE, "faking NAT situation to enforce UDP encapsulation");
+ this->conditions |= COND_NAT_ANY;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ this->conditions &= ~condition;
+ switch (condition)
+ {
+ case COND_NAT_HERE:
+ case COND_NAT_FAKE:
+ case COND_NAT_THERE:
+ set_condition(this, COND_NAT_ANY,
+ has_condition(this, COND_NAT_HERE) ||
+ has_condition(this, COND_NAT_THERE) ||
+ has_condition(this, COND_NAT_FAKE));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.send_dpd
+ */
+static status_t send_dpd(private_ike_sa_t *this)
+{
+ job_t *job;
+ time_t diff, delay;
+
+ delay = this->peer_cfg->get_dpd(this->peer_cfg);
+
+ if (delay == 0)
+ {
+ /* DPD disabled */
+ return SUCCESS;
+ }
+
+ if (this->task_manager->busy(this->task_manager))
+ {
+ /* an exchange is in the air, no need to start a DPD check */
+ diff = 0;
+ }
+ else
+ {
+ /* check if there was any inbound traffic */
+ time_t last_in, now;
+ last_in = get_use_time(this, TRUE);
+ now = time_monotonic(NULL);
+ diff = now - last_in;
+ if (diff >= delay)
+ {
+ /* to long ago, initiate dead peer detection */
+ task_t *task;
+ ike_mobike_t *mobike;
+
+ if (supports_extension(this, EXT_MOBIKE) &&
+ has_condition(this, COND_NAT_HERE))
+ {
+ /* use mobike enabled DPD to detect NAT mapping changes */
+ mobike = ike_mobike_create(&this->public, TRUE);
+ mobike->dpd(mobike);
+ task = &mobike->task;
+ }
+ else
+ {
+ task = (task_t*)ike_dpd_create(TRUE);
+ }
+ diff = 0;
+ DBG1(DBG_IKE, "sending DPD request");
+
+ this->task_manager->queue_task(this->task_manager, task);
+ this->task_manager->initiate(this->task_manager);
+ }
+ }
+ /* recheck in "interval" seconds */
+ job = (job_t*)send_dpd_job_create(this->ike_sa_id);
+ charon->scheduler->schedule_job(charon->scheduler, job, delay - diff);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of ike_sa_t.get_state.
+ */
+static ike_sa_state_t get_state(private_ike_sa_t *this)
+{
+ return this->state;
+}
+
+/**
+ * Implementation of ike_sa_t.set_state.
+ */
+static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
+{
+ DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
+ get_name(this), this->unique_id,
+ ike_sa_state_names, this->state,
+ ike_sa_state_names, state);
+
+ switch (state)
+ {
+ case IKE_ESTABLISHED:
+ {
+ if (this->state == IKE_CONNECTING ||
+ this->state == IKE_PASSIVE)
+ {
+ job_t *job;
+ u_int32_t t;
+
+ /* calculate rekey, reauth and lifetime */
+ this->stats[STAT_ESTABLISHED] = time_monotonic(NULL);
+
+ /* schedule rekeying if we have a time which is smaller than
+ * an already scheduled rekeying */
+ t = this->peer_cfg->get_rekey_time(this->peer_cfg);
+ if (t && (this->stats[STAT_REKEY] == 0 ||
+ (this->stats[STAT_REKEY] > t + this->stats[STAT_ESTABLISHED])))
+ {
+ this->stats[STAT_REKEY] = t + this->stats[STAT_ESTABLISHED];
+ job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, FALSE);
+ charon->scheduler->schedule_job(charon->scheduler, job, t);
+ DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
+ }
+ t = this->peer_cfg->get_reauth_time(this->peer_cfg);
+ if (t && (this->stats[STAT_REAUTH] == 0 ||
+ (this->stats[STAT_REAUTH] > t + this->stats[STAT_ESTABLISHED])))
+ {
+ this->stats[STAT_REAUTH] = t + this->stats[STAT_ESTABLISHED];
+ job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
+ charon->scheduler->schedule_job(charon->scheduler, job, t);
+ DBG1(DBG_IKE, "scheduling reauthentication in %ds", t);
+ }
+ t = this->peer_cfg->get_over_time(this->peer_cfg);
+ if (this->stats[STAT_REKEY] || this->stats[STAT_REAUTH])
+ {
+ if (this->stats[STAT_REAUTH] == 0)
+ {
+ this->stats[STAT_DELETE] = this->stats[STAT_REKEY];
+ }
+ else if (this->stats[STAT_REKEY] == 0)
+ {
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH];
+ }
+ else
+ {
+ this->stats[STAT_DELETE] = min(this->stats[STAT_REKEY],
+ this->stats[STAT_REAUTH]);
+ }
+ this->stats[STAT_DELETE] += t;
+ t = this->stats[STAT_DELETE] - this->stats[STAT_ESTABLISHED];
+ job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
+ charon->scheduler->schedule_job(charon->scheduler, job, t);
+ DBG1(DBG_IKE, "maximum IKE_SA lifetime %ds", t);
+ }
+
+ /* start DPD checks */
+ send_dpd(this);
+ }
+ break;
+ }
+ case IKE_DELETING:
+ {
+ /* delete may fail if a packet gets lost, so set a timeout */
+ job_t *job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
+ charon->scheduler->schedule_job(charon->scheduler, job,
+ HALF_OPEN_IKE_SA_TIMEOUT);
+ break;
+ }
+ default:
+ break;
+ }
+ charon->bus->ike_state_change(charon->bus, &this->public, state);
+ this->state = state;
+}
+
+/**
+ * Implementation of ike_sa_t.reset
+ */
+static void reset(private_ike_sa_t *this)
+{
+ /* the responder ID is reset, as peer may choose another one */
+ if (this->ike_sa_id->is_initiator(this->ike_sa_id))
+ {
+ this->ike_sa_id->set_responder_spi(this->ike_sa_id, 0);
+ }
+
+ set_state(this, IKE_CREATED);
+
+ this->task_manager->reset(this->task_manager, 0, 0);
+}
+
+/**
+ * Implementation of ike_sa_t.get_keymat
+ */
+static keymat_t* get_keymat(private_ike_sa_t *this)
+{
+ return this->keymat;
+}
+
+/**
+ * Implementation of ike_sa_t.set_virtual_ip
+ */
+static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
+{
+ if (local)
+ {
+ DBG1(DBG_IKE, "installing new virtual IP %H", ip);
+ if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
+ this->my_host) == SUCCESS)
+ {
+ if (this->my_virtual_ip)
+ {
+ DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
+ charon->kernel_interface->del_ip(charon->kernel_interface,
+ this->my_virtual_ip);
+ }
+ DESTROY_IF(this->my_virtual_ip);
+ this->my_virtual_ip = ip->clone(ip);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "installing virtual IP %H failed", ip);
+ this->my_virtual_ip = NULL;
+ }
+ }
+ else
+ {
+ DESTROY_IF(this->other_virtual_ip);
+ this->other_virtual_ip = ip->clone(ip);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.get_virtual_ip
+ */
+static host_t* get_virtual_ip(private_ike_sa_t *this, bool local)
+{
+ if (local)
+ {
+ return this->my_virtual_ip;
+ }
+ else
+ {
+ return this->other_virtual_ip;
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.add_additional_address.
+ */
+static void add_additional_address(private_ike_sa_t *this, host_t *host)
+{
+ this->additional_addresses->insert_last(this->additional_addresses, host);
+}
+
+/**
+ * Implementation of ike_sa_t.create_additional_address_iterator.
+ */
+static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
+{
+ return this->additional_addresses->create_iterator(
+ this->additional_addresses, TRUE);
+}
+
+/**
+ * Implementation of ike_sa_t.has_mapping_changed
+ */
+static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
+{
+ if (this->nat_detection_dest.ptr == NULL)
+ {
+ this->nat_detection_dest = chunk_clone(hash);
+ return FALSE;
+ }
+ if (chunk_equals(hash, this->nat_detection_dest))
+ {
+ return FALSE;
+ }
+ free(this->nat_detection_dest.ptr);
+ this->nat_detection_dest = chunk_clone(hash);
+ return TRUE;
+}
+
+/**
+ * Implementation of ike_sa_t.set_pending_updates.
+ */
+static void set_pending_updates(private_ike_sa_t *this, u_int32_t updates)
+{
+ this->pending_updates = updates;
+}
+
+/**
+ * Implementation of ike_sa_t.get_pending_updates.
+ */
+static u_int32_t get_pending_updates(private_ike_sa_t *this)
+{
+ return this->pending_updates;
+}
+
+/**
+ * Update hosts, as addresses may change (NAT)
+ */
+static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
+{
+ bool update = FALSE;
+
+ if (me == NULL)
+ {
+ me = this->my_host;
+ }
+ if (other == NULL)
+ {
+ other = this->other_host;
+ }
+
+ /* apply hosts on first received message */
+ if (this->my_host->is_anyaddr(this->my_host) ||
+ this->other_host->is_anyaddr(this->other_host))
+ {
+ set_my_host(this, me->clone(me));
+ set_other_host(this, other->clone(other));
+ update = TRUE;
+ }
+ else
+ {
+ /* update our address in any case */
+ if (!me->equals(me, this->my_host))
+ {
+ set_my_host(this, me->clone(me));
+ update = TRUE;
+ }
+
+ if (!other->equals(other, this->other_host))
+ {
+ /* update others adress if we are NOT NATed,
+ * and allow port changes if we are NATed */
+ if (!has_condition(this, COND_NAT_HERE) ||
+ other->ip_equals(other, this->other_host))
+ {
+ set_other_host(this, other->clone(other));
+ update = TRUE;
+ }
+ }
+ }
+
+ /* update all associated CHILD_SAs, if required */
+ if (update)
+ {
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ if (child_sa->update(child_sa, this->my_host,
+ this->other_host, this->my_virtual_ip,
+ has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->public.rekey_child_sa(&this->public,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
+ }
+ iterator->destroy(iterator);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.generate
+ */
+static status_t generate_message(private_ike_sa_t *this, message_t *message,
+ packet_t **packet)
+{
+ this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
+ message->set_ike_sa_id(message, this->ike_sa_id);
+ return message->generate(message,
+ this->keymat->get_crypter(this->keymat, FALSE),
+ this->keymat->get_signer(this->keymat, FALSE), packet);
+}
+
+/**
+ * send a notify back to the sender
+ */
+static void send_notify_response(private_ike_sa_t *this, message_t *request,
+ notify_type_t type)
+{
+ message_t *response;
+ packet_t *packet;
+
+ response = message_create();
+ response->set_exchange_type(response, request->get_exchange_type(request));
+ response->set_request(response, FALSE);
+ response->set_message_id(response, request->get_message_id(request));
+ response->add_notify(response, FALSE, type, chunk_empty);
+ if (this->my_host->is_anyaddr(this->my_host))
+ {
+ this->my_host->destroy(this->my_host);
+ this->my_host = request->get_destination(request);
+ this->my_host = this->my_host->clone(this->my_host);
+ }
+ if (this->other_host->is_anyaddr(this->other_host))
+ {
+ this->other_host->destroy(this->other_host);
+ this->other_host = request->get_source(request);
+ this->other_host = this->other_host->clone(this->other_host);
+ }
+ response->set_source(response, this->my_host->clone(this->my_host));
+ response->set_destination(response, this->other_host->clone(this->other_host));
+ if (generate_message(this, response, &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ }
+ response->destroy(response);
+}
+
+/**
+ * Implementation of ike_sa_t.set_kmaddress.
+ */
+static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
+{
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
+ this->local_host = local->clone(local);
+ this->remote_host = remote->clone(remote);
+}
+
+#ifdef ME
+/**
+ * Implementation of ike_sa_t.act_as_mediation_server.
+ */
+static void act_as_mediation_server(private_ike_sa_t *this)
+{
+ charon->mediation_manager->update_sa_id(charon->mediation_manager,
+ this->other_id, this->ike_sa_id);
+ this->is_mediation_server = TRUE;
+}
+
+/**
+ * Implementation of ike_sa_t.get_server_reflexive_host.
+ */
+static host_t *get_server_reflexive_host(private_ike_sa_t *this)
+{
+ return this->server_reflexive_host;
+}
+
+/**
+ * Implementation of ike_sa_t.set_server_reflexive_host.
+ */
+static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host)
+{
+ DESTROY_IF(this->server_reflexive_host);
+ this->server_reflexive_host = host;
+}
+
+/**
+ * Implementation of ike_sa_t.get_connect_id.
+ */
+static chunk_t get_connect_id(private_ike_sa_t *this)
+{
+ return this->connect_id;
+}
+
+/**
+ * Implementation of ike_sa_t.respond
+ */
+static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
+ chunk_t connect_id)
+{
+ ike_me_t *task = ike_me_create(&this->public, TRUE);
+ task->respond(task, peer_id, connect_id);
+ this->task_manager->queue_task(this->task_manager, (task_t*)task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.callback
+ */
+static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
+{
+ ike_me_t *task = ike_me_create(&this->public, TRUE);
+ task->callback(task, peer_id);
+ this->task_manager->queue_task(this->task_manager, (task_t*)task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.relay
+ */
+static status_t relay(private_ike_sa_t *this, identification_t *requester,
+ chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response)
+{
+ ike_me_t *task = ike_me_create(&this->public, TRUE);
+ task->relay(task, requester, connect_id, connect_key, endpoints, response);
+ this->task_manager->queue_task(this->task_manager, (task_t*)task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.initiate_mediation
+ */
+static status_t initiate_mediation(private_ike_sa_t *this,
+ peer_cfg_t *mediated_cfg)
+{
+ ike_me_t *task = ike_me_create(&this->public, TRUE);
+ task->connect(task, mediated_cfg->get_peer_id(mediated_cfg));
+ this->task_manager->queue_task(this->task_manager, (task_t*)task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.initiate_mediated
+ */
+static status_t initiate_mediated(private_ike_sa_t *this, host_t *me,
+ host_t *other, chunk_t connect_id)
+{
+ set_my_host(this, me->clone(me));
+ set_other_host(this, other->clone(other));
+ chunk_free(&this->connect_id);
+ this->connect_id = chunk_clone(connect_id);
+ return this->task_manager->initiate(this->task_manager);
+}
+#endif /* ME */
+
+/**
+ * Resolve DNS host in configuration
+ */
+static void resolve_hosts(private_ike_sa_t *this)
+{
+ host_t *host;
+
+ if (this->remote_host)
+ {
+ host = this->remote_host->clone(this->remote_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+ 0, this->ike_cfg->get_other_port(this->ike_cfg));
+ }
+ if (host)
+ {
+ set_other_host(this, host);
+ }
+
+ if (this->local_host)
+ {
+ host = this->local_host->clone(this->local_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ int family = 0;
+
+ /* use same address family as for other */
+ if (!this->other_host->is_anyaddr(this->other_host))
+ {
+ family = this->other_host->get_family(this->other_host);
+ }
+ host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
+ family, this->ike_cfg->get_my_port(this->ike_cfg));
+
+ if (host && host->is_anyaddr(host) &&
+ !this->other_host->is_anyaddr(this->other_host))
+ {
+ host->destroy(host);
+ host = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, this->other_host, NULL);
+ if (host)
+ {
+ host->set_port(host, this->ike_cfg->get_my_port(this->ike_cfg));
+ }
+ else
+ { /* fallback to address family specific %any(6), if configured */
+ host = host_create_from_dns(
+ this->ike_cfg->get_my_addr(this->ike_cfg),
+ 0, this->ike_cfg->get_my_port(this->ike_cfg));
+ }
+ }
+ }
+ if (host)
+ {
+ set_my_host(this, host);
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.initiate
+ */
+static status_t initiate(private_ike_sa_t *this,
+ child_cfg_t *child_cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
+{
+ task_t *task;
+
+ if (this->state == IKE_CREATED)
+ {
+ resolve_hosts(this);
+
+ if (this->other_host->is_anyaddr(this->other_host)
+#ifdef ME
+ && !this->peer_cfg->get_mediated_by(this->peer_cfg)
+#endif /* ME */
+ )
+ {
+ child_cfg->destroy(child_cfg);
+ DBG1(DBG_IKE, "unable to initiate to %%any");
+ return DESTROY_ME;
+ }
+
+ set_condition(this, COND_ORIGINAL_INITIATOR, TRUE);
+
+ task = (task_t*)ike_vendor_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_natd_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_cert_pre_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_auth_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_cert_post_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_config_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ if (this->peer_cfg->use_mobike(this->peer_cfg))
+ {
+ task = (task_t*)ike_mobike_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ }
+#ifdef ME
+ task = (task_t*)ike_me_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+#endif /* ME */
+ }
+
+#ifdef ME
+ if (this->peer_cfg->is_mediation(this->peer_cfg))
+ {
+ if (this->state == IKE_ESTABLISHED)
+ {
+ /* mediation connection is already established, retrigger state
+ * change to notify bus listeners */
+ DBG1(DBG_IKE, "mediation connection is already up");
+ set_state(this, IKE_ESTABLISHED);
+ }
+ DESTROY_IF(child_cfg);
+ }
+ else
+#endif /* ME */
+ {
+ /* normal IKE_SA with CHILD_SA */
+ task = (task_t*)child_create_create(&this->public, child_cfg, FALSE,
+ tsi, tsr);
+ child_cfg->destroy(child_cfg);
+ if (reqid)
+ {
+ child_create_t *child_create = (child_create_t*)task;
+ child_create->use_reqid(child_create, reqid);
+ }
+ this->task_manager->queue_task(this->task_manager, task);
+
+#ifdef ME
+ if (this->peer_cfg->get_mediated_by(this->peer_cfg))
+ {
+ /* mediated connection, initiate mediation process */
+ job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id);
+ charon->processor->queue_job(charon->processor, job);
+ return SUCCESS;
+ }
+#endif /* ME */
+ }
+
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.process_message.
+ */
+static status_t process_message(private_ike_sa_t *this, message_t *message)
+{
+ status_t status;
+ bool is_request;
+
+ if (this->state == IKE_PASSIVE)
+ { /* do not handle messages in passive state */
+ return FAILED;
+ }
+
+ is_request = message->get_request(message);
+
+ status = message->parse_body(message,
+ this->keymat->get_crypter(this->keymat, TRUE),
+ this->keymat->get_signer(this->keymat, TRUE));
+ if (status != SUCCESS)
+ {
+
+ if (is_request)
+ {
+ switch (status)
+ {
+ case NOT_SUPPORTED:
+ DBG1(DBG_IKE, "critical unknown payloads found");
+ if (is_request)
+ {
+ send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD);
+ }
+ break;
+ case PARSE_ERROR:
+ DBG1(DBG_IKE, "message parsing failed");
+ if (is_request)
+ {
+ send_notify_response(this, message, INVALID_SYNTAX);
+ }
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_IKE, "message verification failed");
+ if (is_request)
+ {
+ send_notify_response(this, message, INVALID_SYNTAX);
+ }
+ break;
+ case FAILED:
+ DBG1(DBG_IKE, "integrity check failed");
+ /* ignored */
+ break;
+ case INVALID_STATE:
+ DBG1(DBG_IKE, "found encrypted message, but no keys available");
+ if (is_request)
+ {
+ send_notify_response(this, message, INVALID_SYNTAX);
+ }
+ default:
+ break;
+ }
+ }
+ DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
+ exchange_type_names, message->get_exchange_type(message),
+ message->get_request(message) ? "request" : "response",
+ message->get_message_id(message));
+
+ if (this->state == IKE_CREATED)
+ { /* invalid initiation attempt, close SA */
+ return DESTROY_ME;
+ }
+ }
+ else
+ {
+ host_t *me, *other;
+
+ me = message->get_destination(message);
+ other = message->get_source(message);
+
+ /* if this IKE_SA is virgin, we check for a config */
+ if (this->ike_cfg == NULL)
+ {
+ job_t *job;
+ this->ike_cfg = charon->backends->get_ike_cfg(charon->backends,
+ me, other);
+ if (this->ike_cfg == NULL)
+ {
+ /* no config found for these hosts, destroy */
+ DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
+ me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
+ send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
+ return DESTROY_ME;
+ }
+ /* add a timeout if peer does not establish it completely */
+ job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE);
+ charon->scheduler->schedule_job(charon->scheduler, job,
+ HALF_OPEN_IKE_SA_TIMEOUT);
+ }
+ this->stats[STAT_INBOUND] = time_monotonic(NULL);
+ /* check if message is trustworthy, and update host information */
+ if (this->state == IKE_CREATED || this->state == IKE_CONNECTING ||
+ message->get_exchange_type(message) != IKE_SA_INIT)
+ {
+ if (!supports_extension(this, EXT_MOBIKE))
+ { /* with MOBIKE, we do no implicit updates */
+ update_hosts(this, me, other);
+ }
+ }
+ status = this->task_manager->process_message(this->task_manager, message);
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ this->state == IKE_ESTABLISHED)
+ { /* authentication completed */
+ flush_auth_cfgs(this);
+ }
+ }
+ return status;
+}
+
+/**
+ * Implementation of ike_sa_t.get_id.
+ */
+static ike_sa_id_t* get_id(private_ike_sa_t *this)
+{
+ return this->ike_sa_id;
+}
+
+/**
+ * Implementation of ike_sa_t.get_my_id.
+ */
+static identification_t* get_my_id(private_ike_sa_t *this)
+{
+ return this->my_id;
+}
+
+/**
+ * Implementation of ike_sa_t.set_my_id.
+ */
+static void set_my_id(private_ike_sa_t *this, identification_t *me)
+{
+ DESTROY_IF(this->my_id);
+ this->my_id = me;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_id.
+ */
+static identification_t* get_other_id(private_ike_sa_t *this)
+{
+ return this->other_id;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_eap_id.
+ */
+static identification_t* get_other_eap_id(private_ike_sa_t *this)
+{
+ identification_t *id = NULL, *current;
+ enumerator_t *enumerator;
+ auth_cfg_t *cfg;
+
+ enumerator = this->other_auths->create_enumerator(this->other_auths);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ /* prefer EAP-Identity of last round */
+ current = cfg->get(cfg, AUTH_RULE_EAP_IDENTITY);
+ if (!current || current->get_type(current) == ID_ANY)
+ {
+ current = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ }
+ if (current && current->get_type(current) != ID_ANY)
+ {
+ id = current;
+ continue;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (id)
+ {
+ return id;
+ }
+ return this->other_id;
+}
+
+/**
+ * Implementation of ike_sa_t.set_other_id.
+ */
+static void set_other_id(private_ike_sa_t *this, identification_t *other)
+{
+ DESTROY_IF(this->other_id);
+ this->other_id = other;
+}
+
+/**
+ * Implementation of ike_sa_t.add_child_sa.
+ */
+static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
+{
+ this->child_sas->insert_last(this->child_sas, child_sa);
+}
+
+/**
+ * Implementation of ike_sa_t.get_child_sa.
+ */
+static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi, bool inbound)
+{
+ iterator_t *iterator;
+ child_sa_t *current, *found = NULL;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current->get_spi(current, inbound) == spi &&
+ current->get_protocol(current) == protocol)
+ {
+ found = current;
+ }
+ }
+ iterator->destroy(iterator);
+ return found;
+}
+
+/**
+ * Implementation of ike_sa_t.create_child_sa_iterator.
+ */
+static iterator_t* create_child_sa_iterator(private_ike_sa_t *this)
+{
+ return this->child_sas->create_iterator(this->child_sas, TRUE);
+}
+
+/**
+ * Implementation of ike_sa_t.rekey_child_sa.
+ */
+static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi)
+{
+ child_rekey_t *child_rekey;
+
+ child_rekey = child_rekey_create(&this->public, protocol, spi);
+ this->task_manager->queue_task(this->task_manager, &child_rekey->task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.delete_child_sa.
+ */
+static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi)
+{
+ child_delete_t *child_delete;
+
+ child_delete = child_delete_create(&this->public, protocol, spi);
+ this->task_manager->queue_task(this->task_manager, &child_delete->task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.destroy_child_sa.
+ */
+static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ status_t status = NOT_FOUND;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ if (child_sa->get_protocol(child_sa) == protocol &&
+ child_sa->get_spi(child_sa, TRUE) == spi)
+ {
+ child_sa->destroy(child_sa);
+ iterator->remove(iterator);
+ status = SUCCESS;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return status;
+}
+
+/**
+ * Implementation of public_ike_sa_t.delete.
+ */
+static status_t delete_(private_ike_sa_t *this)
+{
+ ike_delete_t *ike_delete;
+
+ switch (this->state)
+ {
+ case IKE_ESTABLISHED:
+ case IKE_REKEYING:
+ ike_delete = ike_delete_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, &ike_delete->task);
+ return this->task_manager->initiate(this->task_manager);
+ case IKE_CREATED:
+ DBG1(DBG_IKE, "deleting unestablished IKE_SA");
+ break;
+ case IKE_PASSIVE:
+ break;
+ default:
+ DBG1(DBG_IKE, "destroying IKE_SA in state %N "
+ "without notification", ike_sa_state_names, this->state);
+ charon->bus->ike_updown(charon->bus, &this->public, FALSE);
+ break;
+ }
+ return DESTROY_ME;
+}
+
+/**
+ * Implementation of ike_sa_t.rekey.
+ */
+static status_t rekey(private_ike_sa_t *this)
+{
+ ike_rekey_t *ike_rekey;
+
+ ike_rekey = ike_rekey_create(&this->public, TRUE);
+
+ this->task_manager->queue_task(this->task_manager, &ike_rekey->task);
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.reauth
+ */
+static status_t reauth(private_ike_sa_t *this)
+{
+ task_t *task;
+
+ /* we can't reauthenticate as responder when we use EAP or virtual IPs.
+ * If the peer does not support RFC4478, there is no way to keep the
+ * IKE_SA up. */
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR))
+ {
+ DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
+ if (this->other_virtual_ip != NULL ||
+ has_condition(this, COND_EAP_AUTHENTICATED)
+#ifdef ME
+ /* as mediation server we too cannot reauth the IKE_SA */
+ || this->is_mediation_server
+#endif /* ME */
+ )
+ {
+ time_t now = time_monotonic(NULL);
+
+ DBG1(DBG_IKE, "IKE_SA will timeout in %V",
+ &now, &this->stats[STAT_DELETE]);
+ return FAILED;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "reauthenticating actively");
+ }
+ }
+ task = (task_t*)ike_reauth_create(&this->public);
+ this->task_manager->queue_task(this->task_manager, task);
+
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.reestablish
+ */
+static status_t reestablish(private_ike_sa_t *this)
+{
+ ike_sa_t *new;
+ host_t *host;
+ action_t action;
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ child_cfg_t *child_cfg;
+ bool restart = FALSE;
+ status_t status = FAILED;
+
+ /* check if we have children to keep up at all */
+ iterator = create_child_sa_iterator(this);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ child_cfg = child_sa->get_config(child_sa);
+ if (this->state == IKE_DELETING)
+ {
+ action = child_cfg->get_close_action(child_cfg);
+ }
+ else
+ {
+ action = child_cfg->get_dpd_action(child_cfg);
+ }
+ switch (action)
+ {
+ case ACTION_RESTART:
+ restart = TRUE;
+ break;
+ case ACTION_ROUTE:
+ charon->traps->install(charon->traps, this->peer_cfg, child_cfg);
+ break;
+ default:
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+#ifdef ME
+ /* mediation connections have no children, keep them up anyway */
+ if (this->peer_cfg->is_mediation(this->peer_cfg))
+ {
+ restart = TRUE;
+ }
+#endif /* ME */
+ if (!restart)
+ {
+ return FAILED;
+ }
+
+ /* check if we are able to reestablish this IKE_SA */
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
+ (this->other_virtual_ip != NULL ||
+ has_condition(this, COND_EAP_AUTHENTICATED)
+#ifdef ME
+ || this->is_mediation_server
+#endif /* ME */
+ ))
+ {
+ DBG1(DBG_IKE, "unable to reestablish IKE_SA due asymetric setup");
+ return FAILED;
+ }
+
+ new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
+ new->set_peer_cfg(new, this->peer_cfg);
+ host = this->other_host;
+ new->set_other_host(new, host->clone(host));
+ host = this->my_host;
+ new->set_my_host(new, host->clone(host));
+ /* if we already have a virtual IP, we reuse it */
+ host = this->my_virtual_ip;
+ if (host)
+ {
+ new->set_virtual_ip(new, TRUE, host);
+ }
+
+#ifdef ME
+ if (this->peer_cfg->is_mediation(this->peer_cfg))
+ {
+ status = new->initiate(new, NULL, 0, NULL, NULL);
+ }
+ else
+#endif /* ME */
+ {
+ iterator = create_child_sa_iterator(this);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ child_cfg = child_sa->get_config(child_sa);
+ if (this->state == IKE_DELETING)
+ {
+ action = child_cfg->get_close_action(child_cfg);
+ }
+ else
+ {
+ action = child_cfg->get_dpd_action(child_cfg);
+ }
+ switch (action)
+ {
+ case ACTION_RESTART:
+ DBG1(DBG_IKE, "restarting CHILD_SA %s",
+ child_cfg->get_name(child_cfg));
+ child_cfg->get_ref(child_cfg);
+ status = new->initiate(new, child_cfg, 0, NULL, NULL);
+ break;
+ default:
+ continue;
+ }
+ if (status == DESTROY_ME)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ }
+
+ if (status == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
+ status = FAILED;
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+ status = SUCCESS;
+ }
+ charon->bus->set_sa(charon->bus, &this->public);
+ return status;
+}
+
+/**
+ * Implementation of ike_sa_t.retransmit.
+ */
+static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
+{
+ this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
+ if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
+ {
+ /* send a proper signal to brief interested bus listeners */
+ switch (this->state)
+ {
+ case IKE_CONNECTING:
+ {
+ /* retry IKE_SA_INIT if we have multiple keyingtries */
+ u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
+ this->keyingtry++;
+ if (tries == 0 || tries > this->keyingtry)
+ {
+ DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
+ this->keyingtry + 1, tries);
+ reset(this);
+ return this->task_manager->initiate(this->task_manager);
+ }
+ DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
+ break;
+ }
+ case IKE_DELETING:
+ DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
+ break;
+ case IKE_REKEYING:
+ DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
+ /* FALL */
+ default:
+ reestablish(this);
+ break;
+ }
+ return DESTROY_ME;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of ike_sa_t.set_auth_lifetime.
+ */
+static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
+{
+ u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg);
+ u_int32_t reauth_time = time_monotonic(NULL) + lifetime - reduction;
+
+ if (lifetime < reduction)
+ {
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
+ lifetime);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
+ }
+ else if (this->stats[STAT_REAUTH] == 0 ||
+ this->stats[STAT_REAUTH] > reauth_time)
+ {
+ this->stats[STAT_REAUTH] = reauth_time;
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
+ " in %ds", lifetime, lifetime - reduction);
+ charon->scheduler->schedule_job(charon->scheduler,
+ (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
+ lifetime - reduction);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
+ "reauthentication already scheduled in %ds", lifetime,
+ this->stats[STAT_REAUTH] - time_monotonic(NULL));
+ }
+}
+
+/**
+ * Implementation of ike_sa_t.roam.
+ */
+static status_t roam(private_ike_sa_t *this, bool address)
+{
+ host_t *src;
+ ike_mobike_t *mobike;
+
+ switch (this->state)
+ {
+ case IKE_CREATED:
+ case IKE_DELETING:
+ case IKE_DESTROYING:
+ case IKE_PASSIVE:
+ return SUCCESS;
+ default:
+ break;
+ }
+ /* responder just updates the peer about changed address config */
+ if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
+ {
+ if (supports_extension(this, EXT_MOBIKE) && address)
+ {
+ DBG1(DBG_IKE, "sending address list update using MOBIKE");
+ mobike = ike_mobike_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
+ return this->task_manager->initiate(this->task_manager);
+ }
+ return SUCCESS;
+ }
+
+ /* keep existing path if possible */
+ src = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ this->other_host, this->my_host);
+ if (src)
+ {
+ if (src->ip_equals(src, this->my_host))
+ {
+ DBG2(DBG_IKE, "keeping connection path %H - %H",
+ src, this->other_host);
+ src->destroy(src);
+ set_condition(this, COND_STALE, FALSE);
+ return SUCCESS;
+ }
+ src->destroy(src);
+
+ }
+ else
+ {
+ /* check if we find a route at all */
+ enumerator_t *enumerator;
+ host_t *addr;
+
+ src = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ this->other_host, NULL);
+ if (!src)
+ {
+ enumerator = this->additional_addresses->create_enumerator(
+ this->additional_addresses);
+ while (enumerator->enumerate(enumerator, &addr))
+ {
+ DBG1(DBG_IKE, "looking for a route to %H ...", addr);
+ src = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, addr, NULL);
+ if (src)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ if (!src)
+ {
+ DBG1(DBG_IKE, "no route found to reach %H, MOBIKE update deferred",
+ this->other_host);
+ set_condition(this, COND_STALE, TRUE);
+ return SUCCESS;
+ }
+ src->destroy(src);
+ }
+ set_condition(this, COND_STALE, FALSE);
+
+ /* update addresses with mobike, if supported ... */
+ if (supports_extension(this, EXT_MOBIKE))
+ {
+ DBG1(DBG_IKE, "requesting address change using MOBIKE");
+ mobike = ike_mobike_create(&this->public, TRUE);
+ mobike->roam(mobike, address);
+ this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
+ return this->task_manager->initiate(this->task_manager);
+ }
+ DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
+ /* ... reauth if not */
+ return reauth(this);
+}
+
+/**
+ * Implementation of ike_sa_t.add_configuration_attribute
+ */
+static void add_configuration_attribute(private_ike_sa_t *this,
+ attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attribute_entry_t *entry = malloc_thing(attribute_entry_t);
+
+ entry->handler = handler;
+ entry->type = type;
+ entry->data = chunk_clone(data);
+
+ this->attributes->insert_last(this->attributes, entry);
+}
+
+/**
+ * Implementation of ike_sa_t.inherit.
+ */
+static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
+{
+ child_sa_t *child_sa;
+ attribute_entry_t *entry;
+
+ /* apply hosts and ids */
+ this->my_host->destroy(this->my_host);
+ this->other_host->destroy(this->other_host);
+ this->my_id->destroy(this->my_id);
+ this->other_id->destroy(this->other_id);
+ this->my_host = other->my_host->clone(other->my_host);
+ this->other_host = other->other_host->clone(other->other_host);
+ this->my_id = other->my_id->clone(other->my_id);
+ this->other_id = other->other_id->clone(other->other_id);
+
+ /* apply virtual assigned IPs... */
+ if (other->my_virtual_ip)
+ {
+ this->my_virtual_ip = other->my_virtual_ip;
+ other->my_virtual_ip = NULL;
+ }
+ if (other->other_virtual_ip)
+ {
+ this->other_virtual_ip = other->other_virtual_ip;
+ other->other_virtual_ip = NULL;
+ }
+
+ /* ... and configuration attributes */
+ while (other->attributes->remove_last(other->attributes,
+ (void**)&entry) == SUCCESS)
+ {
+ this->attributes->insert_first(this->attributes, entry);
+ }
+
+ /* inherit all conditions */
+ this->conditions = other->conditions;
+ if (this->conditions & COND_NAT_HERE)
+ {
+ send_keepalive(this);
+ }
+
+#ifdef ME
+ if (other->is_mediation_server)
+ {
+ act_as_mediation_server(this);
+ }
+ else if (other->server_reflexive_host)
+ {
+ this->server_reflexive_host = other->server_reflexive_host->clone(
+ other->server_reflexive_host);
+ }
+#endif /* ME */
+
+ /* adopt all children */
+ while (other->child_sas->remove_last(other->child_sas,
+ (void**)&child_sa) == SUCCESS)
+ {
+ this->child_sas->insert_first(this->child_sas, (void*)child_sa);
+ }
+
+ /* move pending tasks to the new IKE_SA */
+ this->task_manager->adopt_tasks(this->task_manager, other->task_manager);
+
+ /* reauthentication timeout survives a rekeying */
+ if (other->stats[STAT_REAUTH])
+ {
+ time_t reauth, delete, now = time_monotonic(NULL);
+
+ this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];
+ reauth = this->stats[STAT_REAUTH] - now;
+ delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;
+ DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
+ "lifetime reduced to %ds", reauth, delete);
+ charon->scheduler->schedule_job(charon->scheduler,
+ (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE), reauth);
+ charon->scheduler->schedule_job(charon->scheduler,
+ (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE), delete);
+ }
+ /* we have to initate here, there may be new tasks to handle */
+ return this->task_manager->initiate(this->task_manager);
+}
+
+/**
+ * Implementation of ike_sa_t.destroy.
+ */
+static void destroy(private_ike_sa_t *this)
+{
+ attribute_entry_t *entry;
+
+ charon->bus->set_sa(charon->bus, &this->public);
+
+ set_state(this, IKE_DESTROYING);
+
+ /* remove attributes first, as we pass the IKE_SA to the handler */
+ while (this->attributes->remove_last(this->attributes,
+ (void**)&entry) == SUCCESS)
+ {
+ hydra->attributes->release(hydra->attributes, entry->handler,
+ this->other_id, entry->type, entry->data);
+ free(entry->data.ptr);
+ free(entry);
+ }
+ this->attributes->destroy(this->attributes);
+
+ this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
+
+ /* unset SA after here to avoid usage by the listeners */
+ charon->bus->set_sa(charon->bus, NULL);
+
+ this->task_manager->destroy(this->task_manager);
+ this->keymat->destroy(this->keymat);
+
+ if (this->my_virtual_ip)
+ {
+ charon->kernel_interface->del_ip(charon->kernel_interface,
+ this->my_virtual_ip);
+ this->my_virtual_ip->destroy(this->my_virtual_ip);
+ }
+ if (this->other_virtual_ip)
+ {
+ if (this->peer_cfg && this->peer_cfg->get_pool(this->peer_cfg))
+ {
+ hydra->attributes->release_address(hydra->attributes,
+ this->peer_cfg->get_pool(this->peer_cfg),
+ this->other_virtual_ip, get_other_eap_id(this));
+ }
+ this->other_virtual_ip->destroy(this->other_virtual_ip);
+ }
+ this->additional_addresses->destroy_offset(this->additional_addresses,
+ offsetof(host_t, destroy));
+#ifdef ME
+ if (this->is_mediation_server)
+ {
+ charon->mediation_manager->remove(charon->mediation_manager,
+ this->ike_sa_id);
+ }
+ DESTROY_IF(this->server_reflexive_host);
+ chunk_free(&this->connect_id);
+#endif /* ME */
+ free(this->nat_detection_dest.ptr);
+
+ DESTROY_IF(this->my_host);
+ DESTROY_IF(this->other_host);
+ DESTROY_IF(this->my_id);
+ DESTROY_IF(this->other_id);
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
+
+ DESTROY_IF(this->ike_cfg);
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ this->my_auth->destroy(this->my_auth);
+ this->other_auth->destroy(this->other_auth);
+ this->my_auths->destroy_offset(this->my_auths,
+ offsetof(auth_cfg_t, destroy));
+ this->other_auths->destroy_offset(this->other_auths,
+ offsetof(auth_cfg_t, destroy));
+
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
+{
+ private_ike_sa_t *this = malloc_thing(private_ike_sa_t);
+ static u_int32_t unique_id = 0;
+
+ /* Public functions */
+ this->public.get_state = (ike_sa_state_t (*)(ike_sa_t*)) get_state;
+ this->public.set_state = (void (*)(ike_sa_t*,ike_sa_state_t)) set_state;
+ this->public.get_name = (char* (*)(ike_sa_t*))get_name;
+ this->public.get_statistic = (u_int32_t(*)(ike_sa_t*, statistic_t kind))get_statistic;
+ this->public.process_message = (status_t (*)(ike_sa_t*, message_t*)) process_message;
+ this->public.initiate = (status_t (*)(ike_sa_t*,child_cfg_t*,u_int32_t,traffic_selector_t*,traffic_selector_t*)) initiate;
+ this->public.get_ike_cfg = (ike_cfg_t* (*)(ike_sa_t*))get_ike_cfg;
+ this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
+ this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg;
+ this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
+ this->public.get_auth_cfg = (auth_cfg_t*(*)(ike_sa_t*, bool local))get_auth_cfg;
+ this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(ike_sa_t*, bool local))create_auth_cfg_enumerator;
+ this->public.add_auth_cfg = (void(*)(ike_sa_t*, bool local, auth_cfg_t *cfg))add_auth_cfg;
+ this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
+ this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
+ this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
+ this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host;
+ this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host;
+ this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host;
+ this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_other_host;
+ this->public.set_message_id = (void(*)(ike_sa_t*, bool inbound, u_int32_t mid))set_message_id;
+ this->public.update_hosts = (void(*)(ike_sa_t*, host_t *me, host_t *other))update_hosts;
+ this->public.get_my_id = (identification_t* (*)(ike_sa_t*)) get_my_id;
+ this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id;
+ this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id;
+ this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id;
+ this->public.get_other_eap_id = (identification_t* (*)(ike_sa_t*)) get_other_eap_id;
+ this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
+ this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
+ this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
+ this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
+ this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates;
+ this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates;
+ this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
+ this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
+ this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed;
+ this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
+ this->public.delete = (status_t (*)(ike_sa_t*))delete_;
+ this->public.destroy = (void (*)(ike_sa_t*))destroy;
+ this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
+ this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
+ this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat;
+ this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa;
+ this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
+ this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
+ this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
+ this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
+ this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
+ this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
+ this->public.reauth = (status_t (*)(ike_sa_t*))reauth;
+ this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
+ this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime;
+ this->public.roam = (status_t(*)(ike_sa_t*,bool))roam;
+ this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
+ this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
+ this->public.reset = (void (*)(ike_sa_t*))reset;
+ this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id;
+ this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
+ this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
+ this->public.add_configuration_attribute = (void(*)(ike_sa_t*, attribute_handler_t *handler,configuration_attribute_type_t type, chunk_t data))add_configuration_attribute;
+ this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
+#ifdef ME
+ this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
+ this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
+ this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
+ this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id;
+ this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
+ this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,chunk_t)) initiate_mediated;
+ this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
+ this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
+ this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
+#endif /* ME */
+
+ /* initialize private fields */
+ this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ this->child_sas = linked_list_create();
+ this->my_host = host_create_any(AF_INET);
+ this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
+ this->other_host = host_create_any(AF_INET);
+ this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ this->extensions = 0;
+ this->conditions = 0;
+ this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id));
+ this->state = IKE_CREATED;
+ this->keepalive_interval = lib->settings->get_time(lib->settings,
+ "charon.keep_alive", KEEPALIVE_INTERVAL);
+ memset(this->stats, 0, sizeof(this->stats));
+ this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
+ this->ike_cfg = NULL;
+ this->peer_cfg = NULL;
+ this->my_auth = auth_cfg_create();
+ this->other_auth = auth_cfg_create();
+ this->my_auths = linked_list_create();
+ this->other_auths = linked_list_create();
+ this->proposal = NULL;
+ this->task_manager = task_manager_create(&this->public);
+ this->unique_id = ++unique_id;
+ this->my_virtual_ip = NULL;
+ this->other_virtual_ip = NULL;
+ this->additional_addresses = linked_list_create();
+ this->attributes = linked_list_create();
+ this->nat_detection_dest = chunk_empty;
+ this->pending_updates = 0;
+ this->keyingtry = 0;
+ this->local_host = NULL;
+ this->remote_host = NULL;
+#ifdef ME
+ this->is_mediation_server = FALSE;
+ this->server_reflexive_host = NULL;
+ this->connect_id = chunk_empty;
+#endif /* ME */
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
new file mode 100644
index 000000000..c61502edf
--- /dev/null
+++ b/src/libcharon/sa/ike_sa.h
@@ -0,0 +1,921 @@
+/*
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_sa ike_sa
+ * @{ @ingroup sa
+ */
+
+#ifndef IKE_SA_H_
+#define IKE_SA_H_
+
+typedef enum ike_extension_t ike_extension_t;
+typedef enum ike_condition_t ike_condition_t;
+typedef enum ike_sa_state_t ike_sa_state_t;
+typedef enum statistic_t statistic_t;
+typedef struct ike_sa_t ike_sa_t;
+
+#include <library.h>
+#include <attributes/attribute_handler.h>
+#include <encoding/message.h>
+#include <encoding/payloads/proposal_substructure.h>
+#include <encoding/payloads/configuration_attribute.h>
+#include <sa/ike_sa_id.h>
+#include <sa/child_sa.h>
+#include <sa/tasks/task.h>
+#include <sa/keymat.h>
+#include <config/peer_cfg.h>
+#include <config/ike_cfg.h>
+#include <config/auth_cfg.h>
+
+/**
+ * Timeout in seconds after that a half open IKE_SA gets deleted.
+ */
+#define HALF_OPEN_IKE_SA_TIMEOUT 30
+
+/**
+ * Interval to send keepalives when NATed, in seconds.
+ */
+#define KEEPALIVE_INTERVAL 20
+
+/**
+ * After which time rekeying should be retried if it failed, in seconds.
+ */
+#define RETRY_INTERVAL 30
+
+/**
+ * Jitter to subtract from RETRY_INTERVAL to randomize rekey retry.
+ */
+#define RETRY_JITTER 20
+
+/**
+ * Extensions (or optional features) the peer supports
+ */
+enum ike_extension_t {
+
+ /**
+ * peer supports NAT traversal as specified in RFC4306
+ */
+ EXT_NATT = (1<<0),
+
+ /**
+ * peer supports MOBIKE (RFC4555)
+ */
+ EXT_MOBIKE = (1<<1),
+
+ /**
+ * peer supports HTTP cert lookups as specified in RFC4306
+ */
+ EXT_HASH_AND_URL = (1<<2),
+
+ /**
+ * peer supports multiple authentication exchanges, RFC4739
+ */
+ EXT_MULTIPLE_AUTH = (1<<3),
+
+ /**
+ * peer uses strongSwan, accept private use extensions
+ */
+ EXT_STRONGSWAN = (1<<4),
+
+ /**
+ * peer supports EAP-only authentication, draft-eronen-ipsec-ikev2-eap-auth
+ */
+ EXT_EAP_ONLY_AUTHENTICATION = (1<<5),
+};
+
+/**
+ * Conditions of an IKE_SA, change during its lifetime
+ */
+enum ike_condition_t {
+
+ /**
+ * Connection is natted (or faked) somewhere
+ */
+ COND_NAT_ANY = (1<<0),
+
+ /**
+ * we are behind NAT
+ */
+ COND_NAT_HERE = (1<<1),
+
+ /**
+ * other is behind NAT
+ */
+ COND_NAT_THERE = (1<<2),
+
+ /**
+ * Faking NAT to enforce UDP encapsulation
+ */
+ COND_NAT_FAKE = (1<<3),
+
+ /**
+ * peer has been authenticated using EAP at least once
+ */
+ COND_EAP_AUTHENTICATED = (1<<4),
+
+ /**
+ * received a certificate request from the peer
+ */
+ COND_CERTREQ_SEEN = (1<<5),
+
+ /**
+ * Local peer is the "original" IKE initiator. Unaffected from rekeying.
+ */
+ COND_ORIGINAL_INITIATOR = (1<<6),
+
+ /**
+ * IKE_SA is stale, the peer is currently unreachable (MOBIKE)
+ */
+ COND_STALE = (1<<7),
+};
+
+/**
+ * Timing information and statistics to query from an SA
+ */
+enum statistic_t {
+ /** Timestamp of SA establishement */
+ STAT_ESTABLISHED = 0,
+ /** Timestamp of scheudled rekeying */
+ STAT_REKEY,
+ /** Timestamp of scheudled reauthentication */
+ STAT_REAUTH,
+ /** Timestamp of scheudled delete */
+ STAT_DELETE,
+ /** Timestamp of last inbound IKE packet */
+ STAT_INBOUND,
+ /** Timestamp of last outbound IKE packet */
+ STAT_OUTBOUND,
+
+ STAT_MAX
+};
+
+/**
+ * State of an IKE_SA.
+ *
+ * An IKE_SA passes various states in its lifetime. A newly created
+ * SA is in the state CREATED.
+ * @verbatim
+ +----------------+
+ ¦ SA_CREATED ¦
+ +----------------+
+ ¦
+ on initiate()---> ¦ <----- on IKE_SA_INIT received
+ V
+ +----------------+
+ ¦ SA_CONNECTING ¦
+ +----------------+
+ ¦
+ ¦ <----- on IKE_AUTH successfully completed
+ V
+ +----------------+
+ ¦ SA_ESTABLISHED ¦-------------------------+ <-- on rekeying
+ +----------------+ ¦
+ ¦ V
+ on delete()---> ¦ <----- on IKE_SA +-------------+
+ ¦ delete request ¦ SA_REKEYING ¦
+ ¦ received +-------------+
+ V ¦
+ +----------------+ ¦
+ ¦ SA_DELETING ¦<------------------------+ <-- after rekeying
+ +----------------+
+ ¦
+ ¦ <----- after delete() acknowledged
+ ¦
+ \V/
+ X
+ / \
+ @endverbatim
+ */
+enum ike_sa_state_t {
+
+ /**
+ * IKE_SA just got created, but is not initiating nor responding yet.
+ */
+ IKE_CREATED,
+
+ /**
+ * IKE_SA gets initiated actively or passively
+ */
+ IKE_CONNECTING,
+
+ /**
+ * IKE_SA is fully established
+ */
+ IKE_ESTABLISHED,
+
+ /**
+ * IKE_SA is managed externally and does not process messages
+ */
+ IKE_PASSIVE,
+
+ /**
+ * IKE_SA rekeying in progress
+ */
+ IKE_REKEYING,
+
+ /**
+ * IKE_SA is in progress of deletion
+ */
+ IKE_DELETING,
+
+ /**
+ * IKE_SA object gets destroyed
+ */
+ IKE_DESTROYING,
+};
+
+/**
+ * enum names for ike_sa_state_t.
+ */
+extern enum_name_t *ike_sa_state_names;
+
+/**
+ * Class ike_sa_t representing an IKE_SA.
+ *
+ * An IKE_SA contains crypto information related to a connection
+ * with a peer. It contains multiple IPsec CHILD_SA, for which
+ * it is responsible. All traffic is handled by an IKE_SA, using
+ * the task manager and its tasks.
+ */
+struct ike_sa_t {
+
+ /**
+ * Get the id of the SA.
+ *
+ * Returned ike_sa_id_t object is not getting cloned!
+ *
+ * @return ike_sa's ike_sa_id_t
+ */
+ ike_sa_id_t* (*get_id) (ike_sa_t *this);
+
+ /**
+ * Get the numerical ID uniquely defining this IKE_SA.
+ *
+ * @return unique ID
+ */
+ u_int32_t (*get_unique_id) (ike_sa_t *this);
+
+ /**
+ * Get the state of the IKE_SA.
+ *
+ * @return state of the IKE_SA
+ */
+ ike_sa_state_t (*get_state) (ike_sa_t *this);
+
+ /**
+ * Set the state of the IKE_SA.
+ *
+ * @param state state to set for the IKE_SA
+ */
+ void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa);
+
+ /**
+ * Get the name of the connection this IKE_SA uses.
+ *
+ * @return name
+ */
+ char* (*get_name) (ike_sa_t *this);
+
+ /**
+ * Get statistic values from the IKE_SA.
+ *
+ * @param kind kind of requested value
+ * @return value as integer
+ */
+ u_int32_t (*get_statistic)(ike_sa_t *this, statistic_t kind);
+
+ /**
+ * Get the own host address.
+ *
+ * @return host address
+ */
+ host_t* (*get_my_host) (ike_sa_t *this);
+
+ /**
+ * Set the own host address.
+ *
+ * @param me host address
+ */
+ void (*set_my_host) (ike_sa_t *this, host_t *me);
+
+ /**
+ * Get the other peers host address.
+ *
+ * @return host address
+ */
+ host_t* (*get_other_host) (ike_sa_t *this);
+
+ /**
+ * Set the others host address.
+ *
+ * @param other host address
+ */
+ void (*set_other_host) (ike_sa_t *this, host_t *other);
+
+ /**
+ * Update the IKE_SAs host.
+ *
+ * Hosts may be NULL to use current host.
+ *
+ * @param me new local host address, or NULL
+ * @param other new remote host address, or NULL
+ */
+ void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other);
+
+ /**
+ * Get the own identification.
+ *
+ * @return identification
+ */
+ identification_t* (*get_my_id) (ike_sa_t *this);
+
+ /**
+ * Set the own identification.
+ *
+ * @param me identification
+ */
+ void (*set_my_id) (ike_sa_t *this, identification_t *me);
+
+ /**
+ * Get the other peer's identification.
+ *
+ * @return identification
+ */
+ identification_t* (*get_other_id) (ike_sa_t *this);
+
+ /**
+ * Get the others peer identity, but prefer an EAP-Identity.
+ *
+ * @return EAP or IKEv2 identity
+ */
+ identification_t* (*get_other_eap_id)(ike_sa_t *this);
+
+ /**
+ * Set the other peer's identification.
+ *
+ * @param other identification
+ */
+ void (*set_other_id) (ike_sa_t *this, identification_t *other);
+
+ /**
+ * Get the config used to setup this IKE_SA.
+ *
+ * @return ike_config
+ */
+ ike_cfg_t* (*get_ike_cfg) (ike_sa_t *this);
+
+ /**
+ * Set the config to setup this IKE_SA.
+ *
+ * @param config ike_config to use
+ */
+ void (*set_ike_cfg) (ike_sa_t *this, ike_cfg_t* config);
+
+ /**
+ * Get the peer config used by this IKE_SA.
+ *
+ * @return peer_config
+ */
+ peer_cfg_t* (*get_peer_cfg) (ike_sa_t *this);
+
+ /**
+ * Set the peer config to use with this IKE_SA.
+ *
+ * @param config peer_config to use
+ */
+ void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
+
+ /**
+ * Get the authentication config with rules of the current auth round.
+ *
+ * @param local TRUE for local rules, FALSE for remote constraints
+ * @return current cfg
+ */
+ auth_cfg_t* (*get_auth_cfg)(ike_sa_t *this, bool local);
+
+ /**
+ * Insert a completed authentication round.
+ *
+ * @param local TRUE for own rules, FALSE for others constraints
+ * @param cfg auth config to append
+ */
+ void (*add_auth_cfg)(ike_sa_t *this, bool local, auth_cfg_t *cfg);
+
+ /**
+ * Create an enumerator over added authentication rounds.
+ *
+ * @param local TRUE for own rules, FALSE for others constraints
+ * @return enumerator over auth_cfg_t
+ */
+ enumerator_t* (*create_auth_cfg_enumerator)(ike_sa_t *this, bool local);
+
+ /**
+ * Get the selected proposal of this IKE_SA.
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(ike_sa_t *this);
+
+ /**
+ * Set the proposal selected for this IKE_SA.
+ *
+ * @param selected proposal
+ */
+ void (*set_proposal)(ike_sa_t *this, proposal_t *proposal);
+
+ /**
+ * Set the message id of the IKE_SA.
+ *
+ * The IKE_SA stores two message IDs, one for initiating exchanges (send)
+ * and one to respond to exchanges (expect).
+ *
+ * @param initiate TRUE to set message ID for initiating
+ * @param mid message id to set
+ */
+ void (*set_message_id)(ike_sa_t *this, bool initiate, u_int32_t mid);
+
+ /**
+ * Add an additional address for the peer.
+ *
+ * In MOBIKE, a peer may transmit additional addresses where it is
+ * reachable. These are stored in the IKE_SA.
+ * The own list of addresses is not stored, they are queried from
+ * the kernel when required.
+ *
+ * @param host host to add to list
+ */
+ void (*add_additional_address)(ike_sa_t *this, host_t *host);
+
+ /**
+ * Create an iterator over all additional addresses of the peer.
+ *
+ * @return iterator over addresses
+ */
+ iterator_t* (*create_additional_address_iterator)(ike_sa_t *this);
+
+ /**
+ * Check if mappings have changed on a NAT for our source address.
+ *
+ * @param hash received DESTINATION_IP hash
+ * @return TRUE if mappings have changed
+ */
+ bool (*has_mapping_changed)(ike_sa_t *this, chunk_t hash);
+
+ /**
+ * Enable an extension the peer supports.
+ *
+ * If support for an IKE extension is detected, this method is called
+ * to enable that extension and behave accordingly.
+ *
+ * @param extension extension to enable
+ */
+ void (*enable_extension)(ike_sa_t *this, ike_extension_t extension);
+
+ /**
+ * Check if the peer supports an extension.
+ *
+ * @param extension extension to check for support
+ * @return TRUE if peer supports it, FALSE otherwise
+ */
+ bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension);
+
+ /**
+ * Enable/disable a condition flag for this IKE_SA.
+ *
+ * @param condition condition to enable/disable
+ * @param enable TRUE to enable condition, FALSE to disable
+ */
+ void (*set_condition) (ike_sa_t *this, ike_condition_t condition, bool enable);
+
+ /**
+ * Check if a condition flag is set.
+ *
+ * @param condition condition to check
+ * @return TRUE if condition flag set, FALSE otherwise
+ */
+ bool (*has_condition) (ike_sa_t *this, ike_condition_t condition);
+
+ /**
+ * Get the number of queued MOBIKE address updates.
+ *
+ * @return number of pending updates
+ */
+ u_int32_t (*get_pending_updates)(ike_sa_t *this);
+
+ /**
+ * Set the number of queued MOBIKE address updates.
+ *
+ * @param updates number of pending updates
+ */
+ void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates);
+
+#ifdef ME
+ /**
+ * Activate mediation server functionality for this IKE_SA.
+ */
+ void (*act_as_mediation_server) (ike_sa_t *this);
+
+ /**
+ * Get the server reflexive host.
+ *
+ * @return server reflexive host
+ */
+ host_t* (*get_server_reflexive_host) (ike_sa_t *this);
+
+ /**
+ * Set the server reflexive host.
+ *
+ * @param host server reflexive host
+ */
+ void (*set_server_reflexive_host) (ike_sa_t *this, host_t *host);
+
+ /**
+ * Get the connect ID.
+ *
+ * @return connect ID
+ */
+ chunk_t (*get_connect_id) (ike_sa_t *this);
+
+ /**
+ * Initiate the mediation of a mediated connection (i.e. initiate a
+ * ME_CONNECT exchange to a mediation server).
+ *
+ * @param mediated_cfg peer_cfg of the mediated connection
+ * @return
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
+ */
+ status_t (*initiate_mediation) (ike_sa_t *this, peer_cfg_t *mediated_cfg);
+
+ /**
+ * Initiate the mediated connection
+ *
+ * @param me local endpoint (gets cloned)
+ * @param other remote endpoint (gets cloned)
+ * @param connect_id connect ID (gets cloned)
+ * @return
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
+ */
+ status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other,
+ chunk_t connect_id);
+
+ /**
+ * Relay data from one peer to another (i.e. initiate a ME_CONNECT exchange
+ * to a peer).
+ *
+ * Data is cloned.
+ *
+ * @param requester ID of the requesting peer
+ * @param connect_id data of the ME_CONNECTID payload
+ * @param connect_key data of the ME_CONNECTKEY payload
+ * @param endpoints endpoints
+ * @param response TRUE if this is a response
+ * @return
+ * - SUCCESS if relay started
+ * - DESTROY_ME if relay failed
+ */
+ status_t (*relay) (ike_sa_t *this, identification_t *requester,
+ chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response);
+
+ /**
+ * Send a callback to a peer.
+ *
+ * Data is cloned.
+ *
+ * @param peer_id ID of the other peer
+ * @return
+ * - SUCCESS if response started
+ * - DESTROY_ME if response failed
+ */
+ status_t (*callback) (ike_sa_t *this, identification_t *peer_id);
+
+ /**
+ * Respond to a ME_CONNECT request.
+ *
+ * Data is cloned.
+ *
+ * @param peer_id ID of the other peer
+ * @param connect_id the connect ID supplied by the initiator
+ * @return
+ * - SUCCESS if response started
+ * - DESTROY_ME if response failed
+ */
+ status_t (*respond) (ike_sa_t *this, identification_t *peer_id,
+ chunk_t connect_id);
+#endif /* ME */
+
+ /**
+ * Initiate a new connection.
+ *
+ * The configs are owned by the IKE_SA after the call. If the initiate
+ * is triggered by a packet, traffic selectors of the packet can be added
+ * to the CHILD_SA.
+ *
+ * @param child_cfg child config to create CHILD from
+ * @param reqid reqid to use for CHILD_SA, 0 assigne uniquely
+ * @param tsi source of triggering packet
+ * @param tsr destination of triggering packet.
+ * @return
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
+ */
+ status_t (*initiate) (ike_sa_t *this, child_cfg_t *child_cfg,
+ u_int32_t reqid, traffic_selector_t *tsi,
+ traffic_selector_t *tsr);
+
+ /**
+ * Initiates the deletion of an IKE_SA.
+ *
+ * Sends a delete message to the remote peer and waits for
+ * its response. If the response comes in, or a timeout occurs,
+ * the IKE SA gets deleted.
+ *
+ * @return
+ * - SUCCESS if deletion is initialized
+ * - DESTROY_ME, if the IKE_SA is not in
+ * an established state and can not be
+ * deleted (but destroyed).
+ */
+ status_t (*delete) (ike_sa_t *this);
+
+ /**
+ * Update IKE_SAs after network interfaces have changed.
+ *
+ * Whenever the network interface configuration changes, the kernel
+ * interface calls roam() on each IKE_SA. The IKE_SA then checks if
+ * the new network config requires changes, and handles appropriate.
+ * If MOBIKE is supported, addresses are updated; If not, the tunnel is
+ * restarted.
+ *
+ * @param address TRUE if address list changed, FALSE otherwise
+ * @return SUCCESS, FAILED, DESTROY_ME
+ */
+ status_t (*roam)(ike_sa_t *this, bool address);
+
+ /**
+ * Processes a incoming IKEv2-Message.
+ *
+ * Message processing may fail. If a critical failure occurs,
+ * process_message() return DESTROY_ME. Then the caller must
+ * destroy the IKE_SA immediatly, as it is unusable.
+ *
+ * @param message message to process
+ * @return
+ * - SUCCESS
+ * - FAILED
+ * - DESTROY_ME if this IKE_SA MUST be deleted
+ */
+ status_t (*process_message) (ike_sa_t *this, message_t *message);
+
+ /**
+ * Generate a IKE message to send it to the peer.
+ *
+ * This method generates all payloads in the message and encrypts/signs
+ * the packet.
+ *
+ * @param message message to generate
+ * @param packet generated output packet
+ * @return
+ * - SUCCESS
+ * - FAILED
+ * - DESTROY_ME if this IKE_SA MUST be deleted
+ */
+ status_t (*generate_message) (ike_sa_t *this, message_t *message,
+ packet_t **packet);
+
+ /**
+ * Retransmits a request.
+ *
+ * @param message_id ID of the request to retransmit
+ * @return
+ * - SUCCESS
+ * - NOT_FOUND if request doesn't have to be retransmited
+ */
+ status_t (*retransmit) (ike_sa_t *this, u_int32_t message_id);
+
+ /**
+ * Sends a DPD request to the peer.
+ *
+ * To check if a peer is still alive, periodic
+ * empty INFORMATIONAL messages are sent if no
+ * other traffic was received.
+ *
+ * @return
+ * - SUCCESS
+ * - DESTROY_ME, if peer did not respond
+ */
+ status_t (*send_dpd) (ike_sa_t *this);
+
+ /**
+ * Sends a keep alive packet.
+ *
+ * To refresh NAT tables in a NAT router
+ * between the peers, periodic empty
+ * UDP packets are sent if no other traffic
+ * was sent.
+ */
+ void (*send_keepalive) (ike_sa_t *this);
+
+ /**
+ * Get the keying material of this IKE_SA.
+ *
+ * @return per IKE_SA keymat instance
+ */
+ keymat_t* (*get_keymat)(ike_sa_t *this);
+
+ /**
+ * Associates a child SA to this IKE SA
+ *
+ * @param child_sa child_sa to add
+ */
+ void (*add_child_sa) (ike_sa_t *this, child_sa_t *child_sa);
+
+ /**
+ * Get a CHILD_SA identified by protocol and SPI.
+ *
+ * @param protocol protocol of the SA
+ * @param spi SPI of the CHILD_SA
+ * @param inbound TRUE if SPI is inbound, FALSE if outbound
+ * @return child_sa, or NULL if none found
+ */
+ child_sa_t* (*get_child_sa) (ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi, bool inbound);
+
+ /**
+ * Create an iterator over all CHILD_SAs.
+ *
+ * @return iterator
+ */
+ iterator_t* (*create_child_sa_iterator) (ike_sa_t *this);
+
+ /**
+ * Rekey the CHILD SA with the specified reqid.
+ *
+ * Looks for a CHILD SA owned by this IKE_SA, and start the rekeing.
+ *
+ * @param protocol protocol of the SA
+ * @param spi inbound SPI of the CHILD_SA
+ * @return
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS, if rekeying initiated
+ */
+ status_t (*rekey_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+
+ /**
+ * Close the CHILD SA with the specified protocol/SPI.
+ *
+ * Looks for a CHILD SA owned by this IKE_SA, deletes it and
+ * notify's the remote peer about the delete. The associated
+ * states and policies in the kernel get deleted, if they exist.
+ *
+ * @param protocol protocol of the SA
+ * @param spi inbound SPI of the CHILD_SA
+ * @return
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS, if delete message sent
+ */
+ status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+
+ /**
+ * Destroy a CHILD SA with the specified protocol/SPI.
+ *
+ * Looks for a CHILD SA owned by this IKE_SA and destroys it.
+ *
+ * @param protocol protocol of the SA
+ * @param spi inbound SPI of the CHILD_SA
+ * @return
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS
+ */
+ status_t (*destroy_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+
+ /**
+ * Rekey the IKE_SA.
+ *
+ * Sets up a new IKE_SA, moves all CHILDs to it and deletes this IKE_SA.
+ *
+ * @return - SUCCESS, if IKE_SA rekeying initiated
+ */
+ status_t (*rekey) (ike_sa_t *this);
+
+ /**
+ * Reauthenticate the IKE_SA.
+ *
+ * Create a completely new IKE_SA with authentication, recreates all children
+ * within the IKE_SA, closes this IKE_SA.
+ *
+ * @return DESTROY_ME to destroy the IKE_SA
+ */
+ status_t (*reauth) (ike_sa_t *this);
+
+ /**
+ * Restablish the IKE_SA.
+ *
+ * Reestablish an IKE_SA after it has been closed.
+ *
+ * @return DESTROY_ME to destroy the IKE_SA
+ */
+ status_t (*reestablish) (ike_sa_t *this);
+
+ /**
+ * Set the lifetime limit received from a AUTH_LIFETIME notify.
+ *
+ * @param lifetime lifetime in seconds
+ */
+ void (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
+
+ /**
+ * Set the virtual IP to use for this IKE_SA and its children.
+ *
+ * The virtual IP is assigned per IKE_SA, not per CHILD_SA. It has the same
+ * lifetime as the IKE_SA.
+ *
+ * @param local TRUE to set local address, FALSE for remote
+ * @param ip IP to set as virtual IP
+ */
+ void (*set_virtual_ip) (ike_sa_t *this, bool local, host_t *ip);
+
+ /**
+ * Get the virtual IP configured.
+ *
+ * @param local TRUE to get local virtual IP, FALSE for remote
+ * @return host_t *virtual IP
+ */
+ host_t* (*get_virtual_ip) (ike_sa_t *this, bool local);
+
+ /**
+ * Register a configuration attribute to the IKE_SA.
+ *
+ * If an IRAS sends a configuration attribute it is installed and
+ * registered at the IKE_SA. Attributes are inherit()ed and get released
+ * when the IKE_SA is closed.
+ *
+ * @param handler handler installed the attribute, use for release()
+ * @param type configuration attribute type
+ * @param data associated attribute data
+ */
+ void (*add_configuration_attribute)(ike_sa_t *this,
+ attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Set local and remote host addresses to be used for IKE.
+ *
+ * These addresses are communicated via the KMADDRESS field of a MIGRATE
+ * message sent via the NETLINK or PF _KEY kernel socket interface.
+ *
+ * @param local local kmaddress
+ * @param remote remote kmaddress
+ */
+ void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
+
+ /**
+ * Inherit all attributes of other to this after rekeying.
+ *
+ * When rekeying is completed, all CHILD_SAs, the virtual IP and all
+ * outstanding tasks are moved from other to this.
+ * As this call may initiate inherited tasks, a status is returned.
+ *
+ * @param other other task to inherit from
+ * @return DESTROY_ME if initiation of inherited task failed
+ */
+ status_t (*inherit) (ike_sa_t *this, ike_sa_t *other);
+
+ /**
+ * Reset the IKE_SA, useable when initiating fails
+ */
+ void (*reset) (ike_sa_t *this);
+
+ /**
+ * Destroys a ike_sa_t object.
+ */
+ void (*destroy) (ike_sa_t *this);
+};
+
+/**
+ * Creates an ike_sa_t object with a specific ID.
+ *
+ * @param ike_sa_id ike_sa_id_t object to associate with new IKE_SA
+ * @return ike_sa_t object
+ */
+ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id);
+
+#endif /** IKE_SA_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_id.c b/src/libcharon/sa/ike_sa_id.c
new file mode 100644
index 000000000..94c5405f2
--- /dev/null
+++ b/src/libcharon/sa/ike_sa_id.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_sa_id.h"
+
+#include <stdio.h>
+
+
+typedef struct private_ike_sa_id_t private_ike_sa_id_t;
+
+/**
+ * Private data of an ike_sa_id_t object.
+ */
+struct private_ike_sa_id_t {
+ /**
+ * Public interface of ike_sa_id_t.
+ */
+ ike_sa_id_t public;
+
+ /**
+ * SPI of Initiator.
+ */
+ u_int64_t initiator_spi;
+
+ /**
+ * SPI of Responder.
+ */
+ u_int64_t responder_spi;
+
+ /**
+ * Role for specific IKE_SA.
+ */
+ bool is_initiator_flag;
+};
+
+/**
+ * Implementation of ike_sa_id_t.set_responder_spi.
+ */
+static void set_responder_spi (private_ike_sa_id_t *this, u_int64_t responder_spi)
+{
+ this->responder_spi = responder_spi;
+}
+
+/**
+ * Implementation of ike_sa_id_t.set_initiator_spi.
+ */
+static void set_initiator_spi(private_ike_sa_id_t *this, u_int64_t initiator_spi)
+{
+ this->initiator_spi = initiator_spi;
+}
+
+/**
+ * Implementation of ike_sa_id_t.get_initiator_spi.
+ */
+static u_int64_t get_initiator_spi (private_ike_sa_id_t *this)
+{
+ return this->initiator_spi;
+}
+
+/**
+ * Implementation of ike_sa_id_t.get_responder_spi.
+ */
+static u_int64_t get_responder_spi (private_ike_sa_id_t *this)
+{
+ return this->responder_spi;
+}
+
+/**
+ * Implementation of ike_sa_id_t.equals.
+ */
+static bool equals (private_ike_sa_id_t *this, private_ike_sa_id_t *other)
+{
+ if (other == NULL)
+ {
+ return FALSE;
+ }
+ if ((this->is_initiator_flag == other->is_initiator_flag) &&
+ (this->initiator_spi == other->initiator_spi) &&
+ (this->responder_spi == other->responder_spi))
+ {
+ /* private_ike_sa_id's are equal */
+ return TRUE;
+ }
+ else
+ {
+ /* private_ike_sa_id's are not equal */
+ return FALSE;
+ }
+}
+
+/**
+ * Implementation of ike_sa_id_t.replace_values.
+ */
+static void replace_values(private_ike_sa_id_t *this, private_ike_sa_id_t *other)
+{
+ this->initiator_spi = other->initiator_spi;
+ this->responder_spi = other->responder_spi;
+ this->is_initiator_flag = other->is_initiator_flag;
+}
+
+/**
+ * Implementation of ike_sa_id_t.is_initiator.
+ */
+static bool is_initiator(private_ike_sa_id_t *this)
+{
+ return this->is_initiator_flag;
+}
+
+/**
+ * Implementation of ike_sa_id_t.switch_initiator.
+ */
+static bool switch_initiator(private_ike_sa_id_t *this)
+{
+ if (this->is_initiator_flag)
+ {
+ this->is_initiator_flag = FALSE;
+ }
+ else
+ {
+ this->is_initiator_flag = TRUE;
+ }
+ return this->is_initiator_flag;
+}
+
+/**
+ * Implementation of ike_sa_id_t.clone.
+ */
+static ike_sa_id_t* clone_(private_ike_sa_id_t *this)
+{
+ return ike_sa_id_create(this->initiator_spi, this->responder_spi, this->is_initiator_flag);
+}
+
+/**
+ * Implementation of ike_sa_id_t.destroy.
+ */
+static void destroy(private_ike_sa_id_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiator_flag)
+{
+ private_ike_sa_id_t *this = malloc_thing(private_ike_sa_id_t);
+
+ /* public functions */
+ this->public.set_responder_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_responder_spi;
+ this->public.set_initiator_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_initiator_spi;
+ this->public.get_responder_spi = (u_int64_t(*)(ike_sa_id_t*)) get_responder_spi;
+ this->public.get_initiator_spi = (u_int64_t(*)(ike_sa_id_t*)) get_initiator_spi;
+ this->public.equals = (bool(*)(ike_sa_id_t*,ike_sa_id_t*)) equals;
+ this->public.replace_values = (void(*)(ike_sa_id_t*,ike_sa_id_t*)) replace_values;
+ this->public.is_initiator = (bool(*)(ike_sa_id_t*)) is_initiator;
+ this->public.switch_initiator = (bool(*)(ike_sa_id_t*)) switch_initiator;
+ this->public.clone = (ike_sa_id_t*(*)(ike_sa_id_t*)) clone_;
+ this->public.destroy = (void(*)(ike_sa_id_t*))destroy;
+
+ /* private data */
+ this->initiator_spi = initiator_spi;
+ this->responder_spi = responder_spi;
+ this->is_initiator_flag = is_initiator_flag;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ike_sa_id.h b/src/libcharon/sa/ike_sa_id.h
new file mode 100644
index 000000000..a833aa9d6
--- /dev/null
+++ b/src/libcharon/sa/ike_sa_id.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_sa_id ike_sa_id
+ * @{ @ingroup sa
+ */
+
+#ifndef IKE_SA_ID_H_
+#define IKE_SA_ID_H_
+
+typedef struct ike_sa_id_t ike_sa_id_t;
+
+#include <library.h>
+
+/**
+ * An object of type ike_sa_id_t is used to identify an IKE_SA.
+ *
+ * An IKE_SA is identified by its initiator and responder spi's.
+ * Additionaly it contains the role of the actual running IKEv2-Daemon
+ * for the specific IKE_SA (original initiator or responder).
+ */
+struct ike_sa_id_t {
+
+ /**
+ * Set the SPI of the responder.
+ *
+ * This function is called when a request or reply of a IKE_SA_INIT is received.
+ *
+ * @param responder_spi SPI of responder to set
+ */
+ void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi);
+
+ /**
+ * Set the SPI of the initiator.
+ *
+ * @param initiator_spi SPI to set
+ */
+ void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi);
+
+ /**
+ * Get the initiator SPI.
+ *
+ * @return SPI of the initiator
+ */
+ u_int64_t (*get_initiator_spi) (ike_sa_id_t *this);
+
+ /**
+ * Get the responder SPI.
+ *
+ * @return SPI of the responder
+ */
+ u_int64_t (*get_responder_spi) (ike_sa_id_t *this);
+
+ /**
+ * Check if two ike_sa_id_t objects are equal.
+ *
+ * Two ike_sa_id_t objects are equal if both SPI values and the role matches.
+ *
+ * @param other ike_sa_id_t object to check if equal
+ * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise
+ */
+ bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other);
+
+ /**
+ * Replace all values of a given ike_sa_id_t object with values.
+ * from another ike_sa_id_t object.
+ *
+ * After calling this function, both objects are equal.
+ *
+ * @param other ike_sa_id_t object from which values will be taken
+ */
+ void (*replace_values) (ike_sa_id_t *this, ike_sa_id_t *other);
+
+ /**
+ * Get the initiator flag.
+ *
+ * @return TRUE if we are the original initator
+ */
+ bool (*is_initiator) (ike_sa_id_t *this);
+
+ /**
+ * Switche the original initiator flag.
+ *
+ * @return TRUE if we are the original initator after switch, FALSE otherwise
+ */
+ bool (*switch_initiator) (ike_sa_id_t *this);
+
+ /**
+ * Clones a given ike_sa_id_t object.
+ *
+ * @return cloned ike_sa_id_t object
+ */
+ ike_sa_id_t *(*clone) (ike_sa_id_t *this);
+
+ /**
+ * Destroys an ike_sa_id_t object.
+ */
+ void (*destroy) (ike_sa_id_t *this);
+};
+
+/**
+ * Creates an ike_sa_id_t object with specific SPI's and defined role.
+ *
+ * @param initiator_spi initiators SPI
+ * @param responder_spi responders SPI
+ * @param is_initiaor TRUE if we are the original initiator
+ * @return ike_sa_id_t object
+ */
+ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
+ bool is_initiaor);
+
+#endif /** IKE_SA_ID_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
new file mode 100644
index 000000000..3ef0f3bb0
--- /dev/null
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -0,0 +1,1741 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+
+#include "ike_sa_manager.h"
+
+#include <daemon.h>
+#include <sa/ike_sa_id.h>
+#include <bus/bus.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+#include <crypto/hashers/hasher.h>
+
+/* the default size of the hash table (MUST be a power of 2) */
+#define DEFAULT_HASHTABLE_SIZE 1
+
+/* the maximum size of the hash table (MUST be a power of 2) */
+#define MAX_HASHTABLE_SIZE (1 << 30)
+
+/* the default number of segments (MUST be a power of 2) */
+#define DEFAULT_SEGMENT_COUNT 1
+
+typedef struct entry_t entry_t;
+
+/**
+ * An entry in the linked list, contains IKE_SA, locking and lookup data.
+ */
+struct entry_t {
+
+ /**
+ * Number of threads waiting for this ike_sa_t object.
+ */
+ int waiting_threads;
+
+ /**
+ * Condvar where threads can wait until ike_sa_t object is free for use again.
+ */
+ condvar_t *condvar;
+
+ /**
+ * Is this ike_sa currently checked out?
+ */
+ bool checked_out;
+
+ /**
+ * Does this SA drives out new threads?
+ */
+ bool driveout_new_threads;
+
+ /**
+ * Does this SA drives out waiting threads?
+ */
+ bool driveout_waiting_threads;
+
+ /**
+ * Identification of an IKE_SA (SPIs).
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * The contained ike_sa_t object.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * hash of the IKE_SA_INIT message, used to detect retransmissions
+ */
+ chunk_t init_hash;
+
+ /**
+ * remote host address, required for DoS detection
+ */
+ host_t *other;
+
+ /**
+ * As responder: Is this SA half-open?
+ */
+ bool half_open;
+
+ /**
+ * own identity, required for duplicate checking
+ */
+ identification_t *my_id;
+
+ /**
+ * remote identity, required for duplicate checking
+ */
+ identification_t *other_id;
+
+ /**
+ * message ID currently processing, if any
+ */
+ u_int32_t message_id;
+};
+
+/**
+ * Implementation of entry_t.destroy.
+ */
+static status_t entry_destroy(entry_t *this)
+{
+ /* also destroy IKE SA */
+ this->ike_sa->destroy(this->ike_sa);
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ chunk_free(&this->init_hash);
+ DESTROY_IF(this->other);
+ DESTROY_IF(this->my_id);
+ DESTROY_IF(this->other_id);
+ this->condvar->destroy(this->condvar);
+ free(this);
+ return SUCCESS;
+}
+
+/**
+ * Creates a new entry for the ike_sa_t list.
+ */
+static entry_t *entry_create()
+{
+ entry_t *this = malloc_thing(entry_t);
+
+ this->waiting_threads = 0;
+ this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+ /* we set checkout flag when we really give it out */
+ this->checked_out = FALSE;
+ this->driveout_new_threads = FALSE;
+ this->driveout_waiting_threads = FALSE;
+ this->message_id = -1;
+ this->init_hash = chunk_empty;
+ this->other = NULL;
+ this->half_open = FALSE;
+ this->my_id = NULL;
+ this->other_id = NULL;
+ this->ike_sa_id = NULL;
+ this->ike_sa = NULL;
+
+ return this;
+}
+
+/**
+ * Function that matches entry_t objects by initiator SPI and the hash of the
+ * IKE_SA_INIT message.
+ */
+static bool entry_match_by_hash(entry_t *entry, ike_sa_id_t *id, chunk_t *hash)
+{
+ return id->get_responder_spi(id) == 0 &&
+ id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id) &&
+ chunk_equals(*hash, entry->init_hash);
+}
+
+/**
+ * Function that matches entry_t objects by ike_sa_id_t.
+ */
+static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
+{
+ if (id->equals(id, entry->ike_sa_id))
+ {
+ return TRUE;
+ }
+ if ((id->get_responder_spi(id) == 0 ||
+ entry->ike_sa_id->get_responder_spi(entry->ike_sa_id) == 0) &&
+ id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id))
+ {
+ /* this is TRUE for IKE_SAs that we initiated but have not yet received a response */
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Function that matches entry_t objects by ike_sa_t pointers.
+ */
+static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa)
+{
+ return entry->ike_sa == ike_sa;
+}
+
+/**
+ * Hash function for ike_sa_id_t objects.
+ */
+static u_int ike_sa_id_hash(ike_sa_id_t *ike_sa_id)
+{
+ /* we always use initiator spi as key */
+ return ike_sa_id->get_initiator_spi(ike_sa_id);
+}
+
+typedef struct half_open_t half_open_t;
+
+/**
+ * Struct to manage half-open IKE_SAs per peer.
+ */
+struct half_open_t {
+ /** chunk of remote host address */
+ chunk_t other;
+
+ /** the number of half-open IKE_SAs with that host */
+ u_int count;
+};
+
+/**
+ * Destroys a half_open_t object.
+ */
+static void half_open_destroy(half_open_t *this)
+{
+ chunk_free(&this->other);
+ free(this);
+}
+
+/**
+ * Function that matches half_open_t objects by the given IP address chunk.
+ */
+static bool half_open_match(half_open_t *half_open, chunk_t *addr)
+{
+ return chunk_equals(*addr, half_open->other);
+}
+
+typedef struct connected_peers_t connected_peers_t;
+
+struct connected_peers_t {
+ /** own identity */
+ identification_t *my_id;
+
+ /** remote identity */
+ identification_t *other_id;
+
+ /** list of ike_sa_id_t objects of IKE_SAs between the two identities */
+ linked_list_t *sas;
+};
+
+static void connected_peers_destroy(connected_peers_t *this)
+{
+ this->my_id->destroy(this->my_id);
+ this->other_id->destroy(this->other_id);
+ this->sas->destroy(this->sas);
+ free(this);
+}
+
+/**
+ * Function that matches connected_peers_t objects by the given ids.
+ */
+static bool connected_peers_match(connected_peers_t *connected_peers,
+ identification_t *my_id, identification_t *other_id)
+{
+ return my_id->equals(my_id, connected_peers->my_id) &&
+ other_id->equals(other_id, connected_peers->other_id);
+}
+
+typedef struct segment_t segment_t;
+
+/**
+ * Struct to manage segments of the hash table.
+ */
+struct segment_t {
+ /** mutex to access a segment exclusively */
+ mutex_t *mutex;
+
+ /** the number of entries in this segment */
+ u_int count;
+};
+
+typedef struct shareable_segment_t shareable_segment_t;
+
+/**
+ * Struct to manage segments of the "half-open" and "connected peers" hash tables.
+ */
+struct shareable_segment_t {
+ /** rwlock to access a segment non-/exclusively */
+ rwlock_t *lock;
+
+ /** the number of entries in this segment - in case of the "half-open table"
+ * it's the sum of all half_open_t.count in a segment. */
+ u_int count;
+};
+
+typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
+
+/**
+ * Additional private members of ike_sa_manager_t.
+ */
+struct private_ike_sa_manager_t {
+ /**
+ * Public interface of ike_sa_manager_t.
+ */
+ ike_sa_manager_t public;
+
+ /**
+ * Hash table with entries for the ike_sa_t objects.
+ */
+ linked_list_t **ike_sa_table;
+
+ /**
+ * The size of the hash table.
+ */
+ u_int table_size;
+
+ /**
+ * Mask to map the hashes to table rows.
+ */
+ u_int table_mask;
+
+ /**
+ * Segments of the hash table.
+ */
+ segment_t *segments;
+
+ /**
+ * The number of segments.
+ */
+ u_int segment_count;
+
+ /**
+ * Mask to map a table row to a segment.
+ */
+ u_int segment_mask;
+
+ /**
+ * Hash table with half_open_t objects.
+ */
+ linked_list_t **half_open_table;
+
+ /**
+ * Segments of the "half-open" hash table.
+ */
+ shareable_segment_t *half_open_segments;
+
+ /**
+ * Hash table with connected_peers_t objects.
+ */
+ linked_list_t **connected_peers_table;
+
+ /**
+ * Segments of the "connected peers" hash table.
+ */
+ shareable_segment_t *connected_peers_segments;
+
+ /**
+ * RNG to get random SPIs for our side
+ */
+ rng_t *rng;
+
+ /**
+ * SHA1 hasher for IKE_SA_INIT retransmit detection
+ */
+ hasher_t *hasher;
+
+ /**
+ * reuse existing IKE_SAs in checkout_by_config
+ */
+ bool reuse_ikesa;
+};
+
+/**
+ * Acquire a lock to access the segment of the table row with the given index.
+ * It also works with the segment index directly.
+ */
+static void lock_single_segment(private_ike_sa_manager_t *this, u_int index)
+{
+ mutex_t *lock = this->segments[index & this->segment_mask].mutex;
+
+ lock->lock(lock);
+}
+
+/**
+ * Release the lock required to access the segment of the table row with the given index.
+ * It also works with the segment index directly.
+ */
+static void unlock_single_segment(private_ike_sa_manager_t *this, u_int index)
+{
+ mutex_t *lock = this->segments[index & this->segment_mask].mutex;
+
+ lock->unlock(lock);
+}
+
+/**
+ * Lock all segments
+ */
+static void lock_all_segments(private_ike_sa_manager_t *this)
+{
+ u_int i;
+
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->segments[i].mutex->lock(this->segments[i].mutex);
+ }
+}
+
+/**
+ * Unlock all segments
+ */
+static void unlock_all_segments(private_ike_sa_manager_t *this)
+{
+ u_int i;
+
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->segments[i].mutex->unlock(this->segments[i].mutex);
+ }
+}
+
+typedef struct private_enumerator_t private_enumerator_t;
+
+/**
+ * hash table enumerator implementation
+ */
+struct private_enumerator_t {
+
+ /**
+ * implements enumerator interface
+ */
+ enumerator_t enumerator;
+
+ /**
+ * associated ike_sa_manager_t
+ */
+ private_ike_sa_manager_t *manager;
+
+ /**
+ * current segment index
+ */
+ u_int segment;
+
+ /**
+ * currently enumerating entry
+ */
+ entry_t *entry;
+
+ /**
+ * current table row index
+ */
+ u_int row;
+
+ /**
+ * enumerator for the current table row
+ */
+ enumerator_t *current;
+};
+
+/**
+ * Implementation of private_enumerator_t.enumerator.enumerate.
+ */
+static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segment)
+{
+ if (this->entry)
+ {
+ this->entry->condvar->signal(this->entry->condvar);
+ this->entry = NULL;
+ }
+ while (this->segment < this->manager->segment_count)
+ {
+ while (this->row < this->manager->table_size)
+ {
+ if (this->current)
+ {
+ entry_t *item;
+
+ if (this->current->enumerate(this->current, &item))
+ {
+ *entry = this->entry = item;
+ *segment = this->segment;
+ return TRUE;
+ }
+ this->current->destroy(this->current);
+ this->current = NULL;
+ unlock_single_segment(this->manager, this->segment);
+ }
+ else
+ {
+ linked_list_t *list;
+
+ lock_single_segment(this->manager, this->segment);
+ if ((list = this->manager->ike_sa_table[this->row]) != NULL &&
+ list->get_count(list))
+ {
+ this->current = list->create_enumerator(list);
+ continue;
+ }
+ unlock_single_segment(this->manager, this->segment);
+ }
+ this->row += this->manager->segment_count;
+ }
+ this->segment++;
+ this->row = this->segment;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of private_enumerator_t.enumerator.destroy.
+ */
+static void enumerator_destroy(private_enumerator_t *this)
+{
+ if (this->entry)
+ {
+ this->entry->condvar->signal(this->entry->condvar);
+ }
+ if (this->current)
+ {
+ this->current->destroy(this->current);
+ unlock_single_segment(this->manager, this->segment);
+ }
+ free(this);
+}
+
+/**
+ * Creates an enumerator to enumerate the entries in the hash table.
+ */
+static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
+{
+ private_enumerator_t *enumerator = malloc_thing(private_enumerator_t);
+
+ enumerator->enumerator.enumerate = (void*)enumerate;
+ enumerator->enumerator.destroy = (void*)enumerator_destroy;
+ enumerator->manager = this;
+ enumerator->segment = 0;
+ enumerator->entry = NULL;
+ enumerator->row = 0;
+ enumerator->current = NULL;
+
+ return &enumerator->enumerator;
+}
+
+/**
+ * Put an entry into the hash table.
+ * Note: The caller has to unlock the returned segment.
+ */
+static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ linked_list_t *list;
+ u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ lock_single_segment(this, segment);
+ if ((list = this->ike_sa_table[row]) == NULL)
+ {
+ list = this->ike_sa_table[row] = linked_list_create();
+ }
+ list->insert_last(list, entry);
+ this->segments[segment].count++;
+ return segment;
+}
+
+/**
+ * Remove an entry from the hash table.
+ * Note: The caller MUST have a lock on the segment of this entry.
+ */
+static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ linked_list_t *list;
+ u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ if ((list = this->ike_sa_table[row]) != NULL)
+ {
+ entry_t *current;
+
+ enumerator_t *enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == entry)
+ {
+ list->remove_at(list, enumerator);
+ this->segments[segment].count--;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+/**
+ * Remove the entry at the current enumerator position.
+ */
+static void remove_entry_at(private_enumerator_t *this)
+{
+ this->entry = NULL;
+ if (this->current)
+ {
+ linked_list_t *list = this->manager->ike_sa_table[this->row];
+ list->remove_at(list, this->current);
+ this->manager->segments[this->segment].count--;
+ }
+}
+
+/**
+ * Find an entry using the provided match function to compare the entries for
+ * equality.
+ */
+static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
+ ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment,
+ linked_list_match_t match, void *p1, void *p2)
+{
+ entry_t *current;
+ linked_list_t *list;
+ u_int row = ike_sa_id_hash(ike_sa_id) & this->table_mask;
+ u_int seg = row & this->segment_mask;
+
+ lock_single_segment(this, seg);
+ if ((list = this->ike_sa_table[row]) != NULL)
+ {
+ if (list->find_first(list, match, (void**)&current, p1, p2) == SUCCESS)
+ {
+ *entry = current;
+ *segment = seg;
+ /* the locked segment has to be unlocked by the caller */
+ return SUCCESS;
+ }
+ }
+ unlock_single_segment(this, seg);
+ return NOT_FOUND;
+}
+
+/**
+ * Find an entry by ike_sa_id_t.
+ * Note: On SUCCESS, the caller has to unlock the segment.
+ */
+static status_t get_entry_by_id(private_ike_sa_manager_t *this,
+ ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment)
+{
+ return get_entry_by_match_function(this, ike_sa_id, entry, segment,
+ (linked_list_match_t)entry_match_by_id, ike_sa_id, NULL);
+}
+
+/**
+ * Find an entry by initiator SPI and IKE_SA_INIT hash.
+ * Note: On SUCCESS, the caller has to unlock the segment.
+ */
+static status_t get_entry_by_hash(private_ike_sa_manager_t *this,
+ ike_sa_id_t *ike_sa_id, chunk_t hash, entry_t **entry, u_int *segment)
+{
+ return get_entry_by_match_function(this, ike_sa_id, entry, segment,
+ (linked_list_match_t)entry_match_by_hash, ike_sa_id, &hash);
+}
+
+/**
+ * Find an entry by IKE_SA pointer.
+ * Note: On SUCCESS, the caller has to unlock the segment.
+ */
+static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
+ ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment)
+{
+ return get_entry_by_match_function(this, ike_sa_id, entry, segment,
+ (linked_list_match_t)entry_match_by_sa, ike_sa, NULL);
+}
+
+/**
+ * Wait until no other thread is using an IKE_SA, return FALSE if entry not
+ * acquirable.
+ */
+static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry,
+ u_int segment)
+{
+ if (entry->driveout_new_threads)
+ {
+ /* we are not allowed to get this */
+ return FALSE;
+ }
+ while (entry->checked_out && !entry->driveout_waiting_threads)
+ {
+ /* so wait until we can get it for us.
+ * we register us as waiting. */
+ entry->waiting_threads++;
+ entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
+ entry->waiting_threads--;
+ }
+ /* hm, a deletion request forbids us to get this SA, get next one */
+ if (entry->driveout_waiting_threads)
+ {
+ /* we must signal here, others may be waiting on it, too */
+ entry->condvar->signal(entry->condvar);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Put a half-open SA into the hash table.
+ */
+static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ half_open_t *half_open = NULL;
+ linked_list_t *list;
+ chunk_t addr = entry->other->get_address(entry->other);
+ u_int row = chunk_hash(addr) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ rwlock_t *lock = this->half_open_segments[segment].lock;
+ lock->write_lock(lock);
+ if ((list = this->half_open_table[row]) == NULL)
+ {
+ list = this->half_open_table[row] = linked_list_create();
+ }
+ else
+ {
+ half_open_t *current;
+ if (list->find_first(list, (linked_list_match_t)half_open_match,
+ (void**)&current, &addr) == SUCCESS)
+ {
+ half_open = current;
+ half_open->count++;
+ this->half_open_segments[segment].count++;
+ }
+ }
+
+ if (!half_open)
+ {
+ half_open = malloc_thing(half_open_t);
+ half_open->other = chunk_clone(addr);
+ half_open->count = 1;
+ list->insert_last(list, half_open);
+ this->half_open_segments[segment].count++;
+ }
+ lock->unlock(lock);
+}
+
+/**
+ * Remove a half-open SA from the hash table.
+ */
+static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ linked_list_t *list;
+ chunk_t addr = entry->other->get_address(entry->other);
+ u_int row = chunk_hash(addr) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ rwlock_t *lock = this->half_open_segments[segment].lock;
+ lock->write_lock(lock);
+ if ((list = this->half_open_table[row]) != NULL)
+ {
+ half_open_t *current;
+ enumerator_t *enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (half_open_match(current, &addr))
+ {
+ if (--current->count == 0)
+ {
+ list->remove_at(list, enumerator);
+ half_open_destroy(current);
+ }
+ this->half_open_segments[segment].count--;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ lock->unlock(lock);
+}
+
+/**
+ * Put an SA between two peers into the hash table.
+ */
+static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ linked_list_t *list;
+ connected_peers_t *connected_peers = NULL;
+ chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
+ other_id = entry->other_id->get_encoding(entry->other_id);
+ u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ rwlock_t *lock = this->connected_peers_segments[segment].lock;
+ lock->write_lock(lock);
+ if ((list = this->connected_peers_table[row]) == NULL)
+ {
+ list = this->connected_peers_table[row] = linked_list_create();
+ }
+ else
+ {
+ connected_peers_t *current;
+ if (list->find_first(list, (linked_list_match_t)connected_peers_match,
+ (void**)&current, entry->my_id, entry->other_id) == SUCCESS)
+ {
+ connected_peers = current;
+ if (connected_peers->sas->find_first(connected_peers->sas,
+ (linked_list_match_t)entry->ike_sa_id->equals,
+ NULL, entry->ike_sa_id) == SUCCESS)
+ {
+ lock->unlock(lock);
+ return;
+ }
+ }
+ }
+
+ if (!connected_peers)
+ {
+ connected_peers = malloc_thing(connected_peers_t);
+ connected_peers->my_id = entry->my_id->clone(entry->my_id);
+ connected_peers->other_id = entry->other_id->clone(entry->other_id);
+ connected_peers->sas = linked_list_create();
+ list->insert_last(list, connected_peers);
+ }
+ connected_peers->sas->insert_last(connected_peers->sas,
+ entry->ike_sa_id->clone(entry->ike_sa_id));
+ this->connected_peers_segments[segment].count++;
+ lock->unlock(lock);
+}
+
+/**
+ * Remove an SA between two peers from the hash table.
+ */
+static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
+{
+ linked_list_t *list;
+ chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
+ other_id = entry->other_id->get_encoding(entry->other_id);
+ u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ rwlock_t *lock = this->connected_peers_segments[segment].lock;
+ lock->write_lock(lock);
+ if ((list = this->connected_peers_table[row]) != NULL)
+ {
+ connected_peers_t *current;
+ enumerator_t *enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (connected_peers_match(current, entry->my_id, entry->other_id))
+ {
+ ike_sa_id_t *ike_sa_id;
+ enumerator_t *inner = current->sas->create_enumerator(current->sas);
+ while (inner->enumerate(inner, &ike_sa_id))
+ {
+ if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id))
+ {
+ current->sas->remove_at(current->sas, inner);
+ ike_sa_id->destroy(ike_sa_id);
+ this->connected_peers_segments[segment].count--;
+ break;
+ }
+ }
+ inner->destroy(inner);
+ if (current->sas->get_count(current->sas) == 0)
+ {
+ list->remove_at(list, enumerator);
+ connected_peers_destroy(current);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ lock->unlock(lock);
+}
+
+/**
+ * Implementation of private_ike_sa_manager_t.get_next_spi.
+ */
+static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
+{
+ u_int64_t spi;
+
+ this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
+ return spi;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout.
+ */
+static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
+{
+ ike_sa_t *ike_sa = NULL;
+ entry_t *entry;
+ u_int segment;
+
+ DBG2(DBG_MGR, "checkout IKE_SA");
+
+ if (get_entry_by_id(this, ike_sa_id, &entry, &segment) == SUCCESS)
+ {
+ if (wait_for_entry(this, entry, segment))
+ {
+ DBG2(DBG_MGR, "IKE_SA successfully checked out");
+ entry->checked_out = TRUE;
+ ike_sa = entry->ike_sa;
+ }
+ unlock_single_segment(this, segment);
+ }
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout_new.
+ */
+static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
+{
+ ike_sa_id_t *ike_sa_id;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ u_int segment;
+
+ if (initiator)
+ {
+ ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
+ }
+ else
+ {
+ ike_sa_id = ike_sa_id_create(0, get_next_spi(this), FALSE);
+ }
+ ike_sa = ike_sa_create(ike_sa_id);
+
+ DBG2(DBG_MGR, "created IKE_SA");
+
+ if (!initiator)
+ {
+ ike_sa_id->destroy(ike_sa_id);
+ return ike_sa;
+ }
+
+ entry = entry_create();
+ entry->ike_sa_id = ike_sa_id;
+ entry->ike_sa = ike_sa;
+ segment = put_entry(this, entry);
+ entry->checked_out = TRUE;
+ unlock_single_segment(this, segment);
+ return entry->ike_sa;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout_by_message.
+ */
+static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
+ message_t *message)
+{
+ u_int segment;
+ entry_t *entry;
+ ike_sa_t *ike_sa = NULL;
+ ike_sa_id_t *id = message->get_ike_sa_id(message);
+
+ id = id->clone(id);
+ id->switch_initiator(id);
+
+ DBG2(DBG_MGR, "checkout IKE_SA by message");
+
+ if (message->get_request(message) &&
+ message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
+ chunk_t data, hash;
+
+ data = message->get_packet_data(message);
+ this->hasher->allocate_hash(this->hasher, data, &hash);
+ chunk_free(&data);
+
+ if (get_entry_by_hash(this, id, hash, &entry, &segment) == SUCCESS)
+ {
+ if (entry->message_id == 0)
+ {
+ unlock_single_segment(this, segment);
+ chunk_free(&hash);
+ id->destroy(id);
+ DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
+ return NULL;
+ }
+ else if (wait_for_entry(this, entry, segment))
+ {
+ DBG2(DBG_MGR, "IKE_SA checked out by hash");
+ entry->checked_out = TRUE;
+ entry->message_id = message->get_message_id(message);
+ ike_sa = entry->ike_sa;
+ }
+ unlock_single_segment(this, segment);
+ }
+
+ if (ike_sa == NULL)
+ {
+ if (id->get_responder_spi(id) == 0 &&
+ message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ /* no IKE_SA found, create a new one */
+ id->set_responder_spi(id, get_next_spi(this));
+ entry = entry_create();
+ entry->ike_sa = ike_sa_create(id);
+ entry->ike_sa_id = id->clone(id);
+
+ segment = put_entry(this, entry);
+ entry->checked_out = TRUE;
+ unlock_single_segment(this, segment);
+
+ entry->message_id = message->get_message_id(message);
+ entry->init_hash = hash;
+ ike_sa = entry->ike_sa;
+
+ DBG2(DBG_MGR, "created IKE_SA");
+ }
+ else
+ {
+ chunk_free(&hash);
+ DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
+ }
+ }
+ else
+ {
+ chunk_free(&hash);
+ }
+ id->destroy(id);
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+ }
+
+ if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS)
+ {
+ /* only check out if we are not processing this request */
+ if (message->get_request(message) &&
+ message->get_message_id(message) == entry->message_id)
+ {
+ DBG1(DBG_MGR, "ignoring request with ID %d, already processing",
+ entry->message_id);
+ }
+ else if (wait_for_entry(this, entry, segment))
+ {
+ ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
+ DBG2(DBG_MGR, "IKE_SA successfully checked out");
+ entry->checked_out = TRUE;
+ entry->message_id = message->get_message_id(message);
+ if (ike_id->get_responder_spi(ike_id) == 0)
+ {
+ ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
+ }
+ ike_sa = entry->ike_sa;
+ }
+ unlock_single_segment(this, segment);
+ }
+ id->destroy(id);
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout_by_config.
+ */
+static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
+ peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ ike_sa_t *ike_sa = NULL;
+ peer_cfg_t *current_peer;
+ ike_cfg_t *current_ike;
+ u_int segment;
+
+ if (!this->reuse_ikesa)
+ { /* IKE_SA reuse disable by config */
+ ike_sa = checkout_new(this, TRUE);
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+ }
+
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ if (!wait_for_entry(this, entry, segment))
+ {
+ continue;
+ }
+ if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
+ { /* skip IKE_SAs which are not usable */
+ continue;
+ }
+
+ current_peer = entry->ike_sa->get_peer_cfg(entry->ike_sa);
+ if (current_peer && current_peer->equals(current_peer, peer_cfg))
+ {
+ current_ike = current_peer->get_ike_cfg(current_peer);
+ if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg)))
+ {
+ DBG2(DBG_MGR, "found an existing IKE_SA with a '%s' config",
+ current_peer->get_name(current_peer));
+ entry->checked_out = TRUE;
+ ike_sa = entry->ike_sa;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!ike_sa)
+ { /* no IKE_SA using such a config, hand out a new */
+ ike_sa = checkout_new(this, TRUE);
+ }
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout_by_id.
+ */
+static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
+ bool child)
+{
+ enumerator_t *enumerator;
+ iterator_t *children;
+ entry_t *entry;
+ ike_sa_t *ike_sa = NULL;
+ child_sa_t *child_sa;
+ u_int segment;
+
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ if (wait_for_entry(this, entry, segment))
+ {
+ /* look for a child with such a reqid ... */
+ if (child)
+ {
+ children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (child_sa->get_reqid(child_sa) == id)
+ {
+ ike_sa = entry->ike_sa;
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+ else /* ... or for a IKE_SA with such a unique id */
+ {
+ if (entry->ike_sa->get_unique_id(entry->ike_sa) == id)
+ {
+ ike_sa = entry->ike_sa;
+ }
+ }
+ /* got one, return */
+ if (ike_sa)
+ {
+ entry->checked_out = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+}
+
+/**
+ * Implementation of of ike_sa_manager.checkout_by_name.
+ */
+static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
+ bool child)
+{
+ enumerator_t *enumerator;
+ iterator_t *children;
+ entry_t *entry;
+ ike_sa_t *ike_sa = NULL;
+ child_sa_t *child_sa;
+ u_int segment;
+
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ if (wait_for_entry(this, entry, segment))
+ {
+ /* look for a child with such a policy name ... */
+ if (child)
+ {
+ children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (streq(child_sa->get_name(child_sa), name))
+ {
+ ike_sa = entry->ike_sa;
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+ else /* ... or for a IKE_SA with such a connection name */
+ {
+ if (streq(entry->ike_sa->get_name(entry->ike_sa), name))
+ {
+ ike_sa = entry->ike_sa;
+ }
+ }
+ /* got one, return */
+ if (ike_sa)
+ {
+ entry->checked_out = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
+}
+
+/**
+ * enumerator filter function
+ */
+static bool enumerator_filter(private_ike_sa_manager_t *this,
+ entry_t **in, ike_sa_t **out, u_int *segment)
+{
+ if (wait_for_entry(this, *in, *segment))
+ {
+ *out = (*in)->ike_sa;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of ike_sa_manager_t.create_enumerator.
+ */
+static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
+{
+ return enumerator_create_filter(
+ create_table_enumerator(this),
+ (void*)enumerator_filter, this, NULL);
+}
+
+/**
+ * Implementation of ike_sa_manager_t.checkin.
+ */
+static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+{
+ /* to check the SA back in, we look for the pointer of the ike_sa
+ * in all entries.
+ * The lookup is done by initiator SPI, so even if the SPI has changed (e.g.
+ * on reception of a IKE_SA_INIT response) the lookup will work but
+ * updating of the SPI MAY be necessary...
+ */
+ entry_t *entry;
+ ike_sa_id_t *ike_sa_id;
+ host_t *other;
+ identification_t *my_id, *other_id;
+ u_int segment;
+
+ ike_sa_id = ike_sa->get_id(ike_sa);
+ my_id = ike_sa->get_my_id(ike_sa);
+ other_id = ike_sa->get_other_id(ike_sa);
+ other = ike_sa->get_other_host(ike_sa);
+
+ DBG2(DBG_MGR, "checkin IKE_SA");
+
+ /* look for the entry */
+ if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
+ {
+ /* ike_sa_id must be updated */
+ entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
+ /* signal waiting threads */
+ entry->checked_out = FALSE;
+ entry->message_id = -1;
+ /* check if this SA is half-open */
+ if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING)
+ {
+ /* not half open anymore */
+ entry->half_open = FALSE;
+ remove_half_open(this, entry);
+ }
+ else if (entry->half_open && !other->ip_equals(other, entry->other))
+ {
+ /* the other host's IP has changed, we must update the hash table */
+ remove_half_open(this, entry);
+ DESTROY_IF(entry->other);
+ entry->other = other->clone(other);
+ put_half_open(this, entry);
+ }
+ else if (!entry->half_open &&
+ !entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ ike_sa->get_state(ike_sa) == IKE_CONNECTING)
+ {
+ /* this is a new half-open SA */
+ entry->half_open = TRUE;
+ entry->other = other->clone(other);
+ put_half_open(this, entry);
+ }
+ DBG2(DBG_MGR, "check-in of IKE_SA successful.");
+ entry->condvar->signal(entry->condvar);
+ }
+ else
+ {
+ entry = entry_create();
+ entry->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ entry->ike_sa = ike_sa;
+ segment = put_entry(this, entry);
+ }
+
+ /* apply identities for duplicate test (only as responder) */
+ if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ entry->my_id == NULL && entry->other_id == NULL)
+ {
+ entry->my_id = my_id->clone(my_id);
+ entry->other_id = other_id->clone(other_id);
+ put_connected_peers(this, entry);
+ }
+
+ unlock_single_segment(this, segment);
+
+ charon->bus->set_sa(charon->bus, NULL);
+}
+
+/**
+ * Implementation of ike_sa_manager_t.checkin_and_destroy.
+ */
+static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+{
+ /* deletion is a bit complex, we must ensure that no thread is waiting for
+ * this SA.
+ * We take this SA from the table, and start signaling while threads
+ * are in the condvar.
+ */
+ entry_t *entry;
+ ike_sa_id_t *ike_sa_id;
+ u_int segment;
+
+ ike_sa_id = ike_sa->get_id(ike_sa);
+
+ DBG2(DBG_MGR, "checkin and destroy IKE_SA");
+
+ if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
+ {
+ /* drive out waiting threads, as we are in hurry */
+ entry->driveout_waiting_threads = TRUE;
+ /* mark it, so no new threads can get this entry */
+ entry->driveout_new_threads = TRUE;
+ /* wait until all workers have done their work */
+ while (entry->waiting_threads)
+ {
+ /* wake up all */
+ entry->condvar->broadcast(entry->condvar);
+ /* they will wake us again when their work is done */
+ entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
+ }
+ remove_entry(this, entry);
+ unlock_single_segment(this, segment);
+
+ if (entry->half_open)
+ {
+ remove_half_open(this, entry);
+ }
+ if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ entry->my_id && entry->other_id)
+ {
+ remove_connected_peers(this, entry);
+ }
+
+ entry_destroy(entry);
+
+ DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful");
+ }
+ else
+ {
+ DBG1(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
+ ike_sa->destroy(ike_sa);
+ }
+ charon->bus->set_sa(charon->bus, NULL);
+}
+
+
+/**
+ * Implementation of ike_sa_manager_t.check_uniqueness.
+ */
+static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+{
+ bool cancel = FALSE;
+ peer_cfg_t *peer_cfg;
+ unique_policy_t policy;
+ linked_list_t *list, *duplicate_ids = NULL;
+ enumerator_t *enumerator;
+ ike_sa_id_t *duplicate_id = NULL;
+ identification_t *me, *other;
+ u_int row, segment;
+ rwlock_t *lock;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ policy = peer_cfg->get_unique_policy(peer_cfg);
+ if (policy == UNIQUE_NO)
+ {
+ return FALSE;
+ }
+
+ me = ike_sa->get_my_id(ike_sa);
+ other = ike_sa->get_other_id(ike_sa);
+
+ row = chunk_hash_inc(other->get_encoding(other),
+ chunk_hash(me->get_encoding(me))) & this->table_mask;
+ segment = row & this->segment_mask;
+
+ lock = this->connected_peers_segments[segment & this->segment_mask].lock;
+ lock->read_lock(lock);
+ if ((list = this->connected_peers_table[row]) != NULL)
+ {
+ connected_peers_t *current;
+
+ if (list->find_first(list, (linked_list_match_t)connected_peers_match,
+ (void**)&current, me, other) == SUCCESS)
+ {
+ /* clone the list, so we can release the lock */
+ duplicate_ids = current->sas->clone_offset(current->sas,
+ offsetof(ike_sa_id_t, clone));
+ }
+ }
+ lock->unlock(lock);
+
+ if (!duplicate_ids)
+ {
+ return FALSE;
+ }
+
+ enumerator = duplicate_ids->create_enumerator(duplicate_ids);
+ while (enumerator->enumerate(enumerator, &duplicate_id))
+ {
+ status_t status = SUCCESS;
+ ike_sa_t *duplicate;
+
+ duplicate = checkout(this, duplicate_id);
+ if (!duplicate)
+ {
+ continue;
+ }
+ peer_cfg = duplicate->get_peer_cfg(duplicate);
+ if (peer_cfg && peer_cfg->equals(peer_cfg, ike_sa->get_peer_cfg(ike_sa)))
+ {
+ switch (duplicate->get_state(duplicate))
+ {
+ case IKE_ESTABLISHED:
+ case IKE_REKEYING:
+ switch (policy)
+ {
+ case UNIQUE_REPLACE:
+ DBG1(DBG_IKE, "deleting duplicate IKE_SA for peer "
+ "'%Y' due to uniqueness policy", other);
+ status = duplicate->delete(duplicate);
+ break;
+ case UNIQUE_KEEP:
+ cancel = TRUE;
+ /* we keep the first IKE_SA and delete all
+ * other duplicates that might exist */
+ policy = UNIQUE_REPLACE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (status == DESTROY_ME)
+ {
+ checkin_and_destroy(this, duplicate);
+ }
+ else
+ {
+ checkin(this, duplicate);
+ }
+ }
+ enumerator->destroy(enumerator);
+ duplicate_ids->destroy_offset(duplicate_ids, offsetof(ike_sa_id_t, destroy));
+ /* reset thread's current IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return cancel;
+}
+
+/**
+ * Implementation of ike_sa_manager_t.get_half_open_count.
+ */
+static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
+{
+ int count = 0;
+
+ if (ip)
+ {
+ linked_list_t *list;
+ chunk_t addr = ip->get_address(ip);
+ u_int row = chunk_hash(addr) & this->table_mask;
+ u_int segment = row & this->segment_mask;
+
+ rwlock_t *lock = this->half_open_segments[segment & this->segment_mask].lock;
+ lock->read_lock(lock);
+ if ((list = this->half_open_table[row]) != NULL)
+ {
+ half_open_t *current;
+
+ if (list->find_first(list, (linked_list_match_t)half_open_match,
+ (void**)&current, &addr) == SUCCESS)
+ {
+ count = current->count;
+ }
+ }
+ lock->unlock(lock);
+ }
+ else
+ {
+ u_int segment;
+
+ for (segment = 0; segment < this->segment_count; ++segment)
+ {
+ rwlock_t *lock;
+ lock = this->half_open_segments[segment & this->segment_mask].lock;
+ lock->read_lock(lock);
+ count += this->half_open_segments[segment].count;
+ lock->unlock(lock);
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Implementation of ike_sa_manager_t.flush.
+ */
+static void flush(private_ike_sa_manager_t *this)
+{
+ /* destroy all list entries */
+ enumerator_t *enumerator;
+ entry_t *entry;
+ u_int segment;
+
+ lock_all_segments(this);
+ DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
+ /* Step 1: drive out all waiting threads */
+ DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ /* do not accept new threads, drive out waiting threads */
+ entry->driveout_new_threads = TRUE;
+ entry->driveout_waiting_threads = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's");
+ /* Step 2: wait until all are gone */
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ while (entry->waiting_threads || entry->checked_out)
+ {
+ /* wake up all */
+ entry->condvar->broadcast(entry->condvar);
+ /* go sleeping until they are gone */
+ entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
+ }
+ }
+ enumerator->destroy(enumerator);
+ DBG2(DBG_MGR, "delete all IKE_SA's");
+ /* Step 3: initiate deletion of all IKE_SAs */
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
+ /* as the delete never gets processed, fire down events */
+ switch (entry->ike_sa->get_state(entry->ike_sa))
+ {
+ case IKE_ESTABLISHED:
+ case IKE_REKEYING:
+ case IKE_DELETING:
+ charon->bus->ike_updown(charon->bus, entry->ike_sa, FALSE);
+ break;
+ default:
+ break;
+ }
+ entry->ike_sa->delete(entry->ike_sa);
+ }
+ enumerator->destroy(enumerator);
+
+ DBG2(DBG_MGR, "destroy all entries");
+ /* Step 4: destroy all entries */
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
+ if (entry->half_open)
+ {
+ remove_half_open(this, entry);
+ }
+ if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
+ entry->my_id && entry->other_id)
+ {
+ remove_connected_peers(this, entry);
+ }
+ remove_entry_at((private_enumerator_t*)enumerator);
+ entry_destroy(entry);
+ }
+ enumerator->destroy(enumerator);
+ charon->bus->set_sa(charon->bus, NULL);
+ unlock_all_segments(this);
+}
+
+/**
+ * Implementation of ike_sa_manager_t.destroy.
+ */
+static void destroy(private_ike_sa_manager_t *this)
+{
+ u_int i;
+
+ for (i = 0; i < this->table_size; ++i)
+ {
+ linked_list_t *list;
+
+ if ((list = this->ike_sa_table[i]) != NULL)
+ {
+ list->destroy(list);
+ }
+ if ((list = this->half_open_table[i]) != NULL)
+ {
+ list->destroy(list);
+ }
+ if ((list = this->connected_peers_table[i]) != NULL)
+ {
+ list->destroy(list);
+ }
+ }
+ free(this->ike_sa_table);
+ free(this->half_open_table);
+ free(this->connected_peers_table);
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->segments[i].mutex->destroy(this->segments[i].mutex);
+ this->half_open_segments[i].lock->destroy(this->half_open_segments[i].lock);
+ this->connected_peers_segments[i].lock->destroy(this->connected_peers_segments[i].lock);
+ }
+ free(this->segments);
+ free(this->half_open_segments);
+ free(this->connected_peers_segments);
+
+ this->rng->destroy(this->rng);
+ this->hasher->destroy(this->hasher);
+ free(this);
+}
+
+/**
+ * This function returns the next-highest power of two for the given number.
+ * The algorithm works by setting all bits on the right-hand side of the most
+ * significant 1 to 1 and then increments the whole number so it rolls over
+ * to the nearest power of two. Note: returns 0 for n == 0
+ */
+static u_int get_nearest_powerof2(u_int n)
+{
+ u_int i;
+
+ --n;
+ for (i = 1; i < sizeof(u_int) * 8; i <<= 1)
+ {
+ n |= n >> i;
+ }
+ return ++n;
+}
+
+/*
+ * Described in header.
+ */
+ike_sa_manager_t *ike_sa_manager_create()
+{
+ u_int i;
+ private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
+
+ /* assign public functions */
+ this->public.flush = (void(*)(ike_sa_manager_t*))flush;
+ this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
+ this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
+ this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
+ this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
+ this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
+ this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
+ this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
+ this->public.check_uniqueness = (bool(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))check_uniqueness;
+ this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator;
+ this->public.checkin = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
+ this->public.checkin_and_destroy = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
+ this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count;
+
+ /* initialize private variables */
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_MGR, "manager initialization failed, no hasher supported");
+ free(this);
+ return NULL;
+ }
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (this->rng == NULL)
+ {
+ DBG1(DBG_MGR, "manager initialization failed, no RNG supported");
+ this->hasher->destroy(this->hasher);
+ free(this);
+ return NULL;
+ }
+ this->table_size = get_nearest_powerof2(lib->settings->get_int(lib->settings,
+ "charon.ikesa_table_size", DEFAULT_HASHTABLE_SIZE));
+ this->table_size = max(1, min(this->table_size, MAX_HASHTABLE_SIZE));
+ this->table_mask = this->table_size - 1;
+
+ this->segment_count = get_nearest_powerof2(lib->settings->get_int(lib->settings,
+ "charon.ikesa_table_segments", DEFAULT_SEGMENT_COUNT));
+ this->segment_count = max(1, min(this->segment_count, this->table_size));
+ this->segment_mask = this->segment_count - 1;
+
+ this->ike_sa_table = calloc(this->table_size, sizeof(linked_list_t*));
+
+ this->segments = (segment_t*)calloc(this->segment_count, sizeof(segment_t));
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+ this->segments[i].count = 0;
+ }
+
+ /* we use the same table parameters for the table to track half-open SAs */
+ this->half_open_table = calloc(this->table_size, sizeof(linked_list_t*));
+ this->half_open_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->half_open_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ this->half_open_segments[i].count = 0;
+ }
+
+ /* also for the hash table used for duplicate tests */
+ this->connected_peers_table = calloc(this->table_size, sizeof(linked_list_t*));
+ this->connected_peers_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
+ for (i = 0; i < this->segment_count; ++i)
+ {
+ this->connected_peers_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ this->connected_peers_segments[i].count = 0;
+ }
+
+ this->reuse_ikesa = lib->settings->get_bool(lib->settings,
+ "charon.reuse_ikesa", TRUE);
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
new file mode 100644
index 000000000..38f5454e1
--- /dev/null
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_sa_manager ike_sa_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef IKE_SA_MANAGER_H_
+#define IKE_SA_MANAGER_H_
+
+typedef struct ike_sa_manager_t ike_sa_manager_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <encoding/message.h>
+#include <config/peer_cfg.h>
+
+/**
+ * Manages and synchronizes access to all IKE_SAs.
+ *
+ * To synchronize access to thread-unsave IKE_SAs, they are checked out for
+ * use and checked in afterwards. A checked out SA is exclusively accessible
+ * by the owning thread.
+ */
+struct ike_sa_manager_t {
+
+ /**
+ * Checkout an existing IKE_SA.
+ *
+ * @param ike_sa_id the SA identifier, will be updated
+ * @returns
+ * - checked out IKE_SA if found
+ * - NULL, if specified IKE_SA is not found.
+ */
+ ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
+
+ /**
+ * Create and check out a new IKE_SA.
+ *
+ * @note If initiator equals FALSE, the returned IKE_SA is not registered
+ * in the manager.
+ *
+ * @param initiator TRUE for initiator, FALSE otherwise
+ * @returns created and checked out IKE_SA
+ */
+ ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
+
+ /**
+ * Checkout an IKE_SA by a message.
+ *
+ * In some situations, it is necessary that the manager knows the
+ * message to use for the checkout. This has the following reasons:
+ *
+ * 1. If the targeted IKE_SA is already processing a message, we do not
+ * check it out if the message ID is the same.
+ * 2. If it is an IKE_SA_INIT request, we have to check if it is a
+ * retransmission. If so, we have to drop the message, we would
+ * create another unneeded IKE_SA for each retransmitted packet.
+ *
+ * A call to checkout_by_message() returns a (maybe new created) IKE_SA.
+ * If processing the message does not make sense (for the reasons above),
+ * NULL is returned.
+ *
+ * @param ike_sa_id the SA identifier, will be updated
+ * @returns
+ * - checked out/created IKE_SA
+ * - NULL to not process message further
+ */
+ ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
+
+ /**
+ * Checkout an IKE_SA for initiation by a peer_config.
+ *
+ * To initiate, a CHILD_SA may be established within an existing IKE_SA.
+ * This call checks for an existing IKE_SA by comparing the configuration.
+ * If the CHILD_SA can be created in an existing IKE_SA, the matching SA
+ * is returned.
+ * If no IKE_SA is found, a new one is created. This is also the case when
+ * the found IKE_SA is in the DELETING state.
+ *
+ * @param peer_cfg configuration used to find an existing IKE_SA
+ * @return checked out/created IKE_SA
+ */
+ ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this,
+ peer_cfg_t *peer_cfg);
+
+ /**
+ * Check for duplicates of the given IKE_SA.
+ *
+ * Measures are taken according to the uniqueness policy of the IKE_SA.
+ * The return value indicates whether duplicates have been found and if
+ * further measures should be taken (e.g. cancelling an IKE_AUTH exchange).
+ * check_uniqueness() must be called before the IKE_SA is complete,
+ * deadlocks occur otherwise.
+ *
+ * @param ike_sa ike_sa to check
+ * @return TRUE, if the given IKE_SA has duplicates and
+ * should be deleted
+ */
+ bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa);
+
+ /**
+ * Check out an IKE_SA a unique ID.
+ *
+ * Every IKE_SA and every CHILD_SA is uniquely identified by an ID.
+ * These checkout function uses, depending
+ * on the child parameter, the unique ID of the IKE_SA or the reqid
+ * of one of a IKE_SAs CHILD_SA.
+ *
+ * @param id unique ID of the object
+ * @param child TRUE to use CHILD, FALSE to use IKE_SA
+ * @return
+ * - checked out IKE_SA, if found
+ * - NULL, if not found
+ */
+ ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, u_int32_t id,
+ bool child);
+
+ /**
+ * Check out an IKE_SA by the policy/connection name.
+ *
+ * Check out the IKE_SA by the configuration name, either from the IKE- or
+ * one of its CHILD_SAs.
+ *
+ * @param name name of the connection/policy
+ * @param child TRUE to use policy name, FALSE to use conn name
+ * @return
+ * - checked out IKE_SA, if found
+ * - NULL, if not found
+ */
+ ike_sa_t* (*checkout_by_name) (ike_sa_manager_t* this, char *name,
+ bool child);
+
+ /**
+ * Create an enumerator over all stored IKE_SAs.
+ *
+ * While enumerating an IKE_SA, it is temporarily checked out and
+ * automatically checked in after the current enumeration step.
+ *
+ * @return enumerator over all IKE_SAs.
+ */
+ enumerator_t *(*create_enumerator) (ike_sa_manager_t* this);
+
+ /**
+ * Checkin the SA after usage.
+ *
+ * If the IKE_SA is not registered in the manager, a new entry is created.
+ *
+ * @param ike_sa_id the SA identifier, will be updated
+ * @param ike_sa checked out SA
+ */
+ void (*checkin) (ike_sa_manager_t* this, ike_sa_t *ike_sa);
+
+ /**
+ * Destroy a checked out SA.
+ *
+ * The IKE SA is destroyed without notification of the remote peer.
+ * Use this only if the other peer doesn't respond or behaves not
+ * as predicted.
+ * Checking in and destruction is an atomic operation (for the IKE_SA),
+ * so this can be called if the SA is in a "unclean" state, without the
+ * risk that another thread can get the SA.
+ *
+ * @param ike_sa SA to delete
+ */
+ void (*checkin_and_destroy) (ike_sa_manager_t* this, ike_sa_t *ike_sa);
+
+ /**
+ * Get the number of IKE_SAs which are in the connecting state.
+ *
+ * To prevent the server from resource exhaustion, cookies and other
+ * mechanisms are used. The number of half open IKE_SAs is a good
+ * indicator to see if a peer is flooding the server.
+ * If a host is supplied, only the number of half open IKE_SAs initiated
+ * from this IP are counted.
+ * Only SAs for which we are the responder are counted.
+ *
+ * @param ip NULL for all, IP for half open IKE_SAs with IP
+ * @return number of half open IKE_SAs
+ */
+ int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
+
+ /**
+ * Delete all existing IKE_SAs and destroy them immediately.
+ *
+ * Threads will be driven out, so all SAs can be deleted cleanly.
+ */
+ void (*flush)(ike_sa_manager_t *this);
+
+ /**
+ * Destroys the manager with all associated SAs.
+ *
+ * A call to flush() is required before calling destroy.
+ */
+ void (*destroy) (ike_sa_manager_t *this);
+};
+
+/**
+ * Create the IKE_SA manager.
+ *
+ * @returns ike_sa_manager_t object, NULL if initialization fails
+ */
+ike_sa_manager_t *ike_sa_manager_create(void);
+
+#endif /** IKE_SA_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/keymat.c b/src/libcharon/sa/keymat.c
new file mode 100644
index 000000000..837cbe428
--- /dev/null
+++ b/src/libcharon/sa/keymat.c
@@ -0,0 +1,617 @@
+/*
+ * 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.
+ */
+
+#include "keymat.h"
+
+#include <daemon.h>
+#include <crypto/prf_plus.h>
+
+typedef struct private_keymat_t private_keymat_t;
+
+/**
+ * Private data of an keymat_t object.
+ */
+struct private_keymat_t {
+
+ /**
+ * Public keymat_t interface.
+ */
+ keymat_t public;
+
+ /**
+ * IKE_SA Role, initiator or responder
+ */
+ bool initiator;
+
+ /**
+ * inbound signer (verify)
+ */
+ signer_t *signer_in;
+
+ /**
+ * outbound signer (sign)
+ */
+ signer_t *signer_out;
+
+ /**
+ * inbound crypter (decrypt)
+ */
+ crypter_t *crypter_in;
+
+ /**
+ * outbound crypter (encrypt)
+ */
+ crypter_t *crypter_out;
+
+ /**
+ * General purpose PRF
+ */
+ prf_t *prf;
+
+ /**
+ * Negotiated PRF algorithm
+ */
+ pseudo_random_function_t prf_alg;
+
+ /**
+ * Key to derive key material from for CHILD_SAs, rekeying
+ */
+ chunk_t skd;
+
+ /**
+ * Key to build outging authentication data (SKp)
+ */
+ chunk_t skp_build;
+
+ /**
+ * Key to verify incoming authentication data (SKp)
+ */
+ chunk_t skp_verify;
+};
+
+typedef struct keylen_entry_t keylen_entry_t;
+
+/**
+ * Implicit key length for an algorithm
+ */
+struct keylen_entry_t {
+ /** IKEv2 algorithm identifier */
+ int algo;
+ /** key length in bits */
+ int len;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Keylen for encryption algos
+ */
+keylen_entry_t keylen_enc[] = {
+ {ENCR_DES, 64},
+ {ENCR_3DES, 192},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Keylen for integrity algos
+ */
+keylen_entry_t keylen_int[] = {
+ {AUTH_HMAC_MD5_96, 128},
+ {AUTH_HMAC_SHA1_96, 160},
+ {AUTH_HMAC_SHA2_256_96, 256},
+ {AUTH_HMAC_SHA2_256_128, 256},
+ {AUTH_HMAC_SHA2_384_192, 384},
+ {AUTH_HMAC_SHA2_512_256, 512},
+ {AUTH_AES_XCBC_96, 128},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Lookup key length of an algorithm
+ */
+static int lookup_keylen(keylen_entry_t *list, int algo)
+{
+ while (list->algo != END_OF_LIST)
+ {
+ if (algo == list->algo)
+ {
+ return list->len;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of keymat_t.create_dh
+ */
+static diffie_hellman_t* create_dh(private_keymat_t *this,
+ diffie_hellman_group_t group)
+{
+ return lib->crypto->create_dh(lib->crypto, group);;
+}
+
+/**
+ * Implementation of keymat_t.derive_keys
+ */
+static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id,
+ pseudo_random_function_t rekey_function,
+ chunk_t rekey_skd)
+{
+ chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
+ chunk_t spi_i, spi_r;
+ crypter_t *crypter_i, *crypter_r;
+ signer_t *signer_i, *signer_r;
+ prf_plus_t *prf_plus;
+ u_int16_t alg, key_size;
+ prf_t *rekey_prf = NULL;
+
+ spi_i = chunk_alloca(sizeof(u_int64_t));
+ spi_r = chunk_alloca(sizeof(u_int64_t));
+
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+
+ /* Create SAs general purpose PRF first, we may use it here */
+ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return FALSE;
+ }
+ this->prf_alg = alg;
+ this->prf = lib->crypto->create_prf(lib->crypto, alg);
+ if (this->prf == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
+ /* full nonce is used as seed for PRF+ ... */
+ full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ /* but the PRF may need a fixed key which only uses the first bytes of
+ * the nonces. */
+ switch (alg)
+ {
+ case PRF_AES128_XCBC:
+ /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ * not and therefore fixed key semantics apply to XCBC for key
+ * derivation. */
+ key_size = this->prf->get_key_size(this->prf)/2;
+ nonce_i.len = min(nonce_i.len, key_size);
+ nonce_r.len = min(nonce_r.len, key_size);
+ break;
+ default:
+ /* all other algorithms use variable key length, full nonce */
+ break;
+ }
+ fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
+
+ /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
+ *
+ * if we are rekeying, SKEYSEED is built on another way
+ */
+ if (rekey_function == PRF_UNDEFINED) /* not rekeying */
+ {
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+ this->prf->set_key(this->prf, fixed_nonce);
+ this->prf->allocate_bytes(this->prf, secret, &skeyseed);
+ this->prf->set_key(this->prf, skeyseed);
+ prf_plus = prf_plus_create(this->prf, prf_plus_seed);
+ }
+ else
+ {
+ /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
+ * use OLD SAs PRF functions for both prf_plus and prf */
+ rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
+ if (!rekey_prf)
+ {
+ DBG1(DBG_IKE, "PRF of old SA %N not supported!",
+ pseudo_random_function_names, rekey_function);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+ return FALSE;
+ }
+ secret = chunk_cat("mc", secret, full_nonce);
+ rekey_prf->set_key(rekey_prf, rekey_skd);
+ rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed);
+ rekey_prf->set_key(rekey_prf, skeyseed);
+ prf_plus = prf_plus_create(rekey_prf, prf_plus_seed);
+ }
+ DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
+
+ chunk_clear(&skeyseed);
+ chunk_clear(&secret);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+
+ /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
+
+ /* SK_d is used for generating CHILD_SA key mat => store for later use */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &this->skd);
+ DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
+
+ /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, INTEGRITY_ALGORITHM);
+ prf_plus->destroy(prf_plus);
+ DESTROY_IF(rekey_prf);
+ return FALSE;
+ }
+ signer_i = lib->crypto->create_signer(lib->crypto, alg);
+ signer_r = lib->crypto->create_signer(lib->crypto, alg);
+ if (signer_i == NULL || signer_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, INTEGRITY_ALGORITHM,
+ integrity_algorithm_names ,alg);
+ prf_plus->destroy(prf_plus);
+ DESTROY_IF(rekey_prf);
+ return FALSE;
+ }
+ key_size = signer_i->get_key_size(signer_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ai secret %B", &key);
+ signer_i->set_key(signer_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ar secret %B", &key);
+ signer_r->set_key(signer_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->signer_in = signer_r;
+ this->signer_out = signer_i;
+ }
+ else
+ {
+ this->signer_in = signer_i;
+ this->signer_out = signer_r;
+ }
+
+ /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
+ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ prf_plus->destroy(prf_plus);
+ DESTROY_IF(rekey_prf);
+ return FALSE;
+ }
+ crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (crypter_i == NULL || crypter_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, alg, key_size);
+ prf_plus->destroy(prf_plus);
+ DESTROY_IF(rekey_prf);
+ return FALSE;
+ }
+ key_size = crypter_i->get_key_size(crypter_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ei secret %B", &key);
+ crypter_i->set_key(crypter_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_er secret %B", &key);
+ crypter_r->set_key(crypter_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->crypter_in = crypter_r;
+ this->crypter_out = crypter_i;
+ }
+ else
+ {
+ this->crypter_in = crypter_i;
+ this->crypter_out = crypter_r;
+ }
+
+ /* SK_pi/SK_pr used for authentication => stored for later */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pi secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_build = key;
+ }
+ else
+ {
+ this->skp_verify = key;
+ }
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pr secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_verify = key;
+ }
+ else
+ {
+ this->skp_build = key;
+ }
+
+ /* all done, prf_plus not needed anymore */
+ prf_plus->destroy(prf_plus);
+ DESTROY_IF(rekey_prf);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.derive_child_keys
+ */
+static bool derive_child_keys(private_keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r)
+{
+ u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ chunk_t seed, secret = chunk_empty;
+ prf_plus_t *prf_plus;
+
+ if (dh)
+ {
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_CHD, "DH secret %B", &secret);
+ }
+ seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ DBG4(DBG_CHD, "seed %B", &seed);
+
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &enc_size))
+ {
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, enc_alg);
+
+ if (!enc_size)
+ {
+ enc_size = lookup_keylen(keylen_enc, enc_alg);
+ }
+ if (enc_alg != ENCR_NULL && !enc_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ encryption_algorithm_names, enc_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ enc_size /= 8;
+
+ /* CCM/GCM/CTR/GMAC needs additional bytes */
+ switch (enc_alg)
+ {
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ case ENCR_CAMELLIA_CCM_ICV8:
+ case ENCR_CAMELLIA_CCM_ICV12:
+ case ENCR_CAMELLIA_CCM_ICV16:
+ enc_size += 3;
+ break;
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ case ENCR_AES_CTR:
+ case ENCR_NULL_AUTH_AES_GMAC:
+ enc_size += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size))
+ {
+ DBG2(DBG_CHD, " using %N for integrity",
+ integrity_algorithm_names, int_alg);
+
+ if (!int_size)
+ {
+ int_size = lookup_keylen(keylen_int, int_alg);
+ }
+ if (!int_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ integrity_algorithm_names, int_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ int_size /= 8;
+ }
+
+ this->prf->set_key(this->prf, this->skd);
+ prf_plus = prf_plus_create(this->prf, seed);
+
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
+
+ prf_plus->destroy(prf_plus);
+
+ if (enc_size)
+ {
+ DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
+ DBG4(DBG_CHD, "encryption responder key %B", encr_r);
+ }
+ if (int_size)
+ {
+ DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
+ DBG4(DBG_CHD, "integrity responder key %B", integ_r);
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.get_skd
+ */
+static pseudo_random_function_t get_skd(private_keymat_t *this, chunk_t *skd)
+{
+ *skd = this->skd;
+ return this->prf_alg;
+}
+
+/**
+ * Implementation of keymat_t.get_signer
+ */
+static signer_t* get_signer(private_keymat_t *this, bool in)
+{
+ return in ? this->signer_in : this->signer_out;
+}
+
+/**
+ * Implementation of keymat_t.get_crypter
+ */
+static crypter_t* get_crypter(private_keymat_t *this, bool in)
+{
+ return in ? this->crypter_in : this->crypter_out;
+}
+
+/**
+ * Implementation of keymat_t.get_auth_octets
+ */
+static chunk_t get_auth_octets(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce,
+ identification_t *id)
+{
+ chunk_t chunk, idx, octets;
+ chunk_t skp;
+
+ skp = verify ? this->skp_verify : this->skp_build;
+
+ chunk = chunk_alloca(4);
+ memset(chunk.ptr, 0, chunk.len);
+ chunk.ptr[0] = id->get_type(id);
+ idx = chunk_cata("cc", chunk, id->get_encoding(id));
+
+ DBG3(DBG_IKE, "IDx' %B", &idx);
+ DBG3(DBG_IKE, "SK_p %B", &skp);
+ this->prf->set_key(this->prf, skp);
+ this->prf->allocate_bytes(this->prf, idx, &chunk);
+
+ octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
+ DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
+ return octets;
+}
+
+/**
+ * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
+ */
+#define IKEV2_KEY_PAD "Key Pad for IKEv2"
+#define IKEV2_KEY_PAD_LENGTH 17
+
+/**
+ * Implementation of keymat_t.get_psk_sig
+ */
+static chunk_t get_psk_sig(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce, chunk_t secret,
+ identification_t *id)
+{
+ chunk_t key_pad, key, sig, octets;
+
+ if (!secret.len)
+ { /* EAP uses SK_p if no MSK has been established */
+ secret = verify ? this->skp_verify : this->skp_build;
+ }
+ octets = get_auth_octets(this, verify, ike_sa_init, nonce, id);
+ /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
+ key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
+ this->prf->set_key(this->prf, secret);
+ this->prf->allocate_bytes(this->prf, key_pad, &key);
+ this->prf->set_key(this->prf, key);
+ this->prf->allocate_bytes(this->prf, octets, &sig);
+ DBG4(DBG_IKE, "secret %B", &secret);
+ DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
+ DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
+ chunk_free(&octets);
+ chunk_free(&key);
+
+ return sig;
+}
+
+/**
+ * Implementation of keymat_t.destroy.
+ */
+static void destroy(private_keymat_t *this)
+{
+ DESTROY_IF(this->signer_in);
+ DESTROY_IF(this->signer_out);
+ DESTROY_IF(this->crypter_in);
+ DESTROY_IF(this->crypter_out);
+ DESTROY_IF(this->prf);
+ chunk_clear(&this->skd);
+ chunk_clear(&this->skp_verify);
+ chunk_clear(&this->skp_build);
+ free(this);
+}
+
+/**
+ * See header
+ */
+keymat_t *keymat_create(bool initiator)
+{
+ private_keymat_t *this = malloc_thing(private_keymat_t);
+
+ this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh;
+ this->public.derive_ike_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t,chunk_t))derive_ike_keys;
+ this->public.derive_child_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r))derive_child_keys;
+ this->public.get_skd = (pseudo_random_function_t(*)(keymat_t*, chunk_t *skd))get_skd;
+ this->public.get_signer = (signer_t*(*)(keymat_t*, bool in))get_signer;
+ this->public.get_crypter = (crypter_t*(*)(keymat_t*, bool in))get_crypter;
+ this->public.get_auth_octets = (chunk_t(*)(keymat_t *, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id))get_auth_octets;
+ this->public.get_psk_sig = (chunk_t(*)(keymat_t*, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id))get_psk_sig;
+ this->public.destroy = (void(*)(keymat_t*))destroy;
+
+ this->initiator = initiator;
+
+ this->signer_in = NULL;
+ this->signer_out = NULL;
+ this->crypter_in = NULL;
+ this->crypter_out = NULL;
+ this->prf = NULL;
+ this->prf_alg = PRF_UNDEFINED;
+ this->skd = chunk_empty;
+ this->skp_verify = chunk_empty;
+ this->skp_build = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
new file mode 100644
index 000000000..e51709e8d
--- /dev/null
+++ b/src/libcharon/sa/keymat.h
@@ -0,0 +1,163 @@
+/*
+ * 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 keymat keymat
+ * @{ @ingroup sa
+ */
+
+#ifndef KEYMAT_H_
+#define KEYMAT_H_
+
+#include <library.h>
+#include <utils/identification.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <config/proposal.h>
+#include <sa/ike_sa_id.h>
+
+typedef struct keymat_t keymat_t;
+
+/**
+ * Derivation an management of sensitive keying material.
+ */
+struct keymat_t {
+
+ /**
+ * Create a diffie hellman object for key agreement.
+ *
+ * The diffie hellman is either for IKE negotiation/rekeying or
+ * CHILD_SA rekeying (using PFS). The resulting DH object must be passed
+ * to derive_keys or to derive_child_keys and destroyed after use
+ *
+ * @param group diffie hellman group
+ * @return DH object, NULL if group not supported
+ */
+ diffie_hellman_t* (*create_dh)(keymat_t *this, diffie_hellman_group_t group);
+
+ /**
+ * Derive keys for the IKE_SA.
+ *
+ * These keys are not handed out, but are used by the associated signers,
+ * crypters and authentication functions.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh()
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param id IKE_SA identifier
+ * @param rekey_prf PRF of old SA if rekeying, PRF_UNDEFINED otherwise
+ * @param rekey_sdk SKd of old SA if rekeying
+ * @return TRUE on success
+ */
+ bool (*derive_ike_keys)(keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id,
+ pseudo_random_function_t rekey_function,
+ chunk_t rekey_skd);
+ /**
+ * Derive keys for a CHILD_SA.
+ *
+ * The keys for the CHILD_SA are allocated in the integ and encr chunks.
+ * An implementation might hand out encrypted keys only, which are
+ * decrypted in the kernel before use.
+ * If no PFS is used for the CHILD_SA, dh can be NULL.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh(), or NULL
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param encr_i chunk to write initiators encryption key to
+ * @param integ_i chunk to write initiators integrity key to
+ * @param encr_r chunk to write responders encryption key to
+ * @param integ_r chunk to write responders integrity key to
+ * @return TRUE on success
+ */
+ bool (*derive_child_keys)(keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r);
+ /**
+ * Get SKd to pass to derive_ikey_keys() during rekeying.
+ *
+ * @param skd chunk to write SKd to (internal data)
+ * @return PRF function to derive keymat
+ */
+ pseudo_random_function_t (*get_skd)(keymat_t *this, chunk_t *skd);
+
+ /**
+ * Get a signer to sign/verify IKE messages.
+ *
+ * @param in TRUE for inbound (verify), FALSE for outbound (sign)
+ * @return signer
+ */
+ signer_t* (*get_signer)(keymat_t *this, bool in);
+
+ /*
+ * Get a crypter to en-/decrypt IKE messages.
+ *
+ * @param in TRUE for inbound (decrypt), FALSE for outbound (encrypt)
+ * @return crypter
+ */
+ crypter_t* (*get_crypter)(keymat_t *this, bool in);
+
+ /**
+ * Generate octets to use for authentication procedure (RFC4306 2.15).
+ *
+ * This method creates the plain octets and is usually signed by a private
+ * key. PSK and EAP authentication include a secret into the data, use
+ * the get_psk_sig() method instead.
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param id identity
+ * @return authentication octets
+ */
+ chunk_t (*get_auth_octets)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, identification_t *id);
+ /**
+ * Build the shared secret signature used for PSK and EAP authentication.
+ *
+ * This method wraps the get_auth_octets() method and additionally
+ * includes the secret into the signature. If no secret is given, SK_p is
+ * used as secret (used for EAP methods without MSK).
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param secret optional secret to include into signature
+ * @param id identity
+ * @return signature octets
+ */
+ chunk_t (*get_psk_sig)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, chunk_t secret, identification_t *id);
+ /**
+ * Destroy a keymat_t.
+ */
+ void (*destroy)(keymat_t *this);
+};
+
+/**
+ * Create a keymat instance.
+ *
+ * @param initiator TRUE if we are the initiator
+ * @return keymat instance
+ */
+keymat_t *keymat_create(bool initiator);
+
+#endif /** KEYMAT_H_ @}*/
diff --git a/src/libcharon/sa/mediation_manager.c b/src/libcharon/sa/mediation_manager.c
new file mode 100644
index 000000000..035f49053
--- /dev/null
+++ b/src/libcharon/sa/mediation_manager.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2007 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 "mediation_manager.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <processing/jobs/mediation_job.h>
+
+typedef struct peer_t peer_t;
+
+/**
+ * An entry in the linked list.
+ */
+struct peer_t {
+ /** id of the peer */
+ identification_t *id;
+
+ /** sa id of the peer, NULL if offline */
+ ike_sa_id_t *ike_sa_id;
+
+ /** list of peer ids that reuested this peer */
+ linked_list_t *requested_by;
+};
+
+/**
+ * Implementation of peer_t.destroy.
+ */
+static void peer_destroy(peer_t *this)
+{
+ DESTROY_IF(this->id);
+ DESTROY_IF(this->ike_sa_id);
+ this->requested_by->destroy_offset(this->requested_by,
+ offsetof(identification_t, destroy));
+ free(this);
+}
+
+/**
+ * Creates a new entry for the list.
+ */
+static peer_t *peer_create(identification_t *id, ike_sa_id_t* ike_sa_id)
+{
+ peer_t *this = malloc_thing(peer_t);
+
+ /* clone everything */
+ this->id = id->clone(id);
+ this->ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL;
+ this->requested_by = linked_list_create();
+
+ return this;
+}
+
+typedef struct private_mediation_manager_t private_mediation_manager_t;
+
+/**
+ * Additional private members of mediation_manager_t.
+ */
+struct private_mediation_manager_t {
+ /**
+ * Public interface of mediation_manager_t.
+ */
+ mediation_manager_t public;
+
+ /**
+ * Lock for exclusivly accessing the manager.
+ */
+ mutex_t *mutex;
+
+ /**
+ * Linked list with state entries.
+ */
+ linked_list_t *peers;
+};
+
+/**
+ * Registers a peer's ID at another peer, if it is not yet registered
+ */
+static void register_peer(peer_t *peer, identification_t *peer_id)
+{
+ iterator_t *iterator;
+ identification_t *current;
+
+ iterator = peer->requested_by->create_iterator(peer->requested_by, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (peer_id->equals(peer_id, current))
+ {
+ iterator->destroy(iterator);
+ return;
+ }
+ }
+ iterator->destroy(iterator);
+
+ peer->requested_by->insert_last(peer->requested_by,
+ peer_id->clone(peer_id));
+}
+
+/**
+ * Get a peer_t object by a peer's id
+ */
+static status_t get_peer_by_id(private_mediation_manager_t *this,
+ identification_t *id, peer_t **peer)
+{
+ iterator_t *iterator;
+ peer_t *current;
+ status_t status = NOT_FOUND;
+
+ iterator = this->peers->create_iterator(this->peers, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (id->equals(id, current->id))
+ {
+ if (peer)
+ {
+ *peer = current;
+ }
+ status = SUCCESS;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return status;
+}
+
+/**
+ * Check if a given peer is registered at other peers. If so, remove it there
+ * and then remove peers completely that are not online and have no registered
+ * peers.
+ */
+static void unregister_peer(private_mediation_manager_t *this,
+ identification_t *peer_id)
+{
+ iterator_t *iterator, *iterator_r;
+ peer_t *peer;
+ identification_t *registered;
+
+ iterator = this->peers->create_iterator(this->peers, TRUE);
+ while (iterator->iterate(iterator, (void**)&peer))
+ {
+ iterator_r = peer->requested_by->create_iterator(peer->requested_by,
+ TRUE);
+ while (iterator_r->iterate(iterator_r, (void**)&registered))
+ {
+ if (peer_id->equals(peer_id, registered))
+ {
+ iterator_r->remove(iterator_r);
+ registered->destroy(registered);
+ break;
+ }
+ }
+ iterator_r->destroy(iterator_r);
+
+ if (!peer->ike_sa_id && !peer->requested_by->get_count(peer->requested_by))
+ {
+ iterator->remove(iterator);
+ peer_destroy(peer);
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Implementation of mediation_manager_t.remove
+ */
+static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
+{
+ iterator_t *iterator;
+ peer_t *peer;
+
+ this->mutex->lock(this->mutex);
+
+ iterator = this->peers->create_iterator(this->peers, TRUE);
+ while (iterator->iterate(iterator, (void**)&peer))
+ {
+ if (ike_sa_id->equals(ike_sa_id, peer->ike_sa_id))
+ {
+ iterator->remove(iterator);
+
+ unregister_peer(this, peer->id);
+
+ peer_destroy(peer);
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of mediation_manager_t.update_sa_id
+ */
+static void update_sa_id(private_mediation_manager_t *this, identification_t *peer_id, ike_sa_id_t *ike_sa_id)
+{
+ iterator_t *iterator;
+ peer_t *peer;
+ bool found = FALSE;
+
+ this->mutex->lock(this->mutex);
+
+ iterator = this->peers->create_iterator(this->peers, TRUE);
+ while (iterator->iterate(iterator, (void**)&peer))
+ {
+ if (peer_id->equals(peer_id, peer->id))
+ {
+ DESTROY_IF(peer->ike_sa_id);
+ found = TRUE;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (!found)
+ {
+ DBG2(DBG_IKE, "adding peer '%Y'", peer_id);
+ peer = peer_create(peer_id, NULL);
+ this->peers->insert_last(this->peers, peer);
+ }
+
+ DBG2(DBG_IKE, "changing registered IKE_SA ID of peer '%Y'", peer_id);
+ peer->ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL;
+
+ /* send callbacks to registered peers */
+ identification_t *requester;
+ while(peer->requested_by->remove_last(peer->requested_by,
+ (void**)&requester) == SUCCESS)
+ {
+ job_t *job = (job_t*)mediation_callback_job_create(requester, peer_id);
+ charon->processor->queue_job(charon->processor, job);
+ requester->destroy(requester);
+ }
+
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of mediation_manager_t.check.
+ */
+static ike_sa_id_t *check(private_mediation_manager_t *this,
+ identification_t *peer_id)
+{
+ peer_t *peer;
+ ike_sa_id_t *ike_sa_id;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ return NULL;
+ }
+
+ ike_sa_id = peer->ike_sa_id;
+
+ this->mutex->unlock(this->mutex);
+
+ return ike_sa_id;
+}
+
+/**
+ * Implementation of mediation_manager_t.check_and_register.
+ */
+static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
+ identification_t *peer_id, identification_t *requester)
+{
+ peer_t *peer;
+ ike_sa_id_t *ike_sa_id;
+
+ this->mutex->lock(this->mutex);
+
+ if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
+ {
+ DBG2(DBG_IKE, "adding peer %Y", peer_id);
+ peer = peer_create(peer_id, NULL);
+ this->peers->insert_last(this->peers, peer);
+ }
+
+ if (!peer->ike_sa_id)
+ {
+ /* the peer is not online */
+ DBG2(DBG_IKE, "requested peer '%Y' is offline, registering peer '%Y'",
+ peer_id, requester);
+ register_peer(peer, requester);
+ this->mutex->unlock(this->mutex);
+ return NULL;
+ }
+
+ ike_sa_id = peer->ike_sa_id;
+
+ this->mutex->unlock(this->mutex);
+
+ return ike_sa_id;
+}
+
+/**
+ * Implementation of mediation_manager_t.destroy.
+ */
+static void destroy(private_mediation_manager_t *this)
+{
+ this->mutex->lock(this->mutex);
+
+ this->peers->destroy_function(this->peers, (void*)peer_destroy);
+
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+mediation_manager_t *mediation_manager_create()
+{
+ private_mediation_manager_t *this = malloc_thing(private_mediation_manager_t);
+
+ this->public.destroy = (void(*)(mediation_manager_t*))destroy;
+ this->public.remove = (void(*)(mediation_manager_t*,ike_sa_id_t*))remove_sa;
+ this->public.update_sa_id = (void(*)(mediation_manager_t*,identification_t*,ike_sa_id_t*))update_sa_id;
+ this->public.check = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*))check;
+ this->public.check_and_register = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*,identification_t*))check_and_register;
+
+ this->peers = linked_list_create();
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+
+ return (mediation_manager_t*)this;
+}
diff --git a/src/libcharon/sa/mediation_manager.h b/src/libcharon/sa/mediation_manager.h
new file mode 100644
index 000000000..31a16f69c
--- /dev/null
+++ b/src/libcharon/sa/mediation_manager.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 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 mediation_manager mediation_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef MEDIATION_MANAGER_H_
+#define MEDIATION_MANAGER_H_
+
+typedef struct mediation_manager_t mediation_manager_t;
+
+#include <sa/ike_sa_id.h>
+#include <utils/identification.h>
+
+/**
+ * The mediation manager is responsible for managing currently online
+ * peers and registered requests for offline peers on the mediation server.
+ */
+struct mediation_manager_t {
+
+ /**
+ * Remove the IKE_SA of a peer.
+ *
+ * @param ike_sa_id the IKE_SA ID of the peer's SA
+ */
+ void (*remove) (mediation_manager_t* this, ike_sa_id_t *ike_sa_id);
+
+ /**
+ * Update the ike_sa_id that is assigned to a peer's ID. If the peer
+ * is new, it gets a new record assigned.
+ *
+ * @param peer_id the peer's ID
+ * @param ike_sa_id the IKE_SA ID of the peer's SA
+ */
+ void (*update_sa_id) (mediation_manager_t* this, identification_t *peer_id,
+ ike_sa_id_t *ike_sa_id);
+
+ /**
+ * Checks if a specific peer is online.
+ *
+ * @param peer_id the peer's ID
+ * @returns
+ * - IKE_SA ID of the peer's SA.
+ * - NULL, if the peer is not online.
+ */
+ ike_sa_id_t* (*check) (mediation_manager_t* this,
+ identification_t *peer_id);
+
+ /**
+ * Checks if a specific peer is online and registers the requesting
+ * peer if it is not.
+ *
+ * @param peer_id the peer's ID
+ * @param requester the requesters ID
+ * @returns
+ * - IKE_SA ID of the peer's SA.
+ * - NULL, if the peer is not online.
+ */
+ ike_sa_id_t* (*check_and_register) (mediation_manager_t* this,
+ identification_t *peer_id,
+ identification_t *requester);
+
+ /**
+ * Destroys the manager with all data.
+ */
+ void (*destroy) (mediation_manager_t *this);
+};
+
+/**
+ * Create a manager.
+ *
+ * @returns mediation_manager_t object
+ */
+mediation_manager_t *mediation_manager_create(void);
+
+#endif /** MEDIATION_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
new file mode 100644
index 000000000..eeda6c860
--- /dev/null
+++ b/src/libcharon/sa/task_manager.c
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "task_manager.h"
+
+#include <math.h>
+
+#include <daemon.h>
+#include <sa/tasks/ike_init.h>
+#include <sa/tasks/ike_natd.h>
+#include <sa/tasks/ike_mobike.h>
+#include <sa/tasks/ike_auth.h>
+#include <sa/tasks/ike_auth_lifetime.h>
+#include <sa/tasks/ike_cert_pre.h>
+#include <sa/tasks/ike_cert_post.h>
+#include <sa/tasks/ike_rekey.h>
+#include <sa/tasks/ike_delete.h>
+#include <sa/tasks/ike_config.h>
+#include <sa/tasks/ike_dpd.h>
+#include <sa/tasks/ike_vendor.h>
+#include <sa/tasks/child_create.h>
+#include <sa/tasks/child_rekey.h>
+#include <sa/tasks/child_delete.h>
+#include <encoding/payloads/delete_payload.h>
+#include <processing/jobs/retransmit_job.h>
+
+#ifdef ME
+#include <sa/tasks/ike_me.h>
+#endif
+
+typedef struct exchange_t exchange_t;
+
+/**
+ * An exchange in the air, used do detect and handle retransmission
+ */
+struct exchange_t {
+
+ /**
+ * Message ID used for this transaction
+ */
+ u_int32_t mid;
+
+ /**
+ * generated packet for retransmission
+ */
+ packet_t *packet;
+};
+
+typedef struct private_task_manager_t private_task_manager_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_task_manager_t {
+
+ /**
+ * public functions
+ */
+ task_manager_t public;
+
+ /**
+ * associated IKE_SA we are serving
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Exchange we are currently handling as responder
+ */
+ struct {
+ /**
+ * Message ID of the exchange
+ */
+ u_int32_t mid;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ } responding;
+
+ /**
+ * Exchange we are currently handling as initiator
+ */
+ struct {
+ /**
+ * Message ID of the exchange
+ */
+ u_int32_t mid;
+
+ /**
+ * how many times we have retransmitted so far
+ */
+ u_int retransmitted;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ /**
+ * type of the initated exchange
+ */
+ exchange_type_t type;
+
+ } initiating;
+
+ /**
+ * List of queued tasks not yet in action
+ */
+ linked_list_t *queued_tasks;
+
+ /**
+ * List of active tasks, initiated by ourselve
+ */
+ linked_list_t *active_tasks;
+
+ /**
+ * List of tasks initiated by peer
+ */
+ linked_list_t *passive_tasks;
+
+ /**
+ * the task manager has been reset
+ */
+ bool reset;
+
+ /**
+ * Number of times we retransmit messages before giving up
+ */
+ u_int retransmit_tries;
+
+ /**
+ * Retransmission timeout
+ */
+ double retransmit_timeout;
+
+ /**
+ * Base to calculate retransmission timeout
+ */
+ double retransmit_base;
+};
+
+/**
+ * flush all tasks in the task manager
+ */
+static void flush(private_task_manager_t *this)
+{
+ this->queued_tasks->destroy_offset(this->queued_tasks,
+ offsetof(task_t, destroy));
+ this->passive_tasks->destroy_offset(this->passive_tasks,
+ offsetof(task_t, destroy));
+ this->active_tasks->destroy_offset(this->active_tasks,
+ offsetof(task_t, destroy));
+ this->queued_tasks = linked_list_create();
+ this->passive_tasks = linked_list_create();
+ this->active_tasks = linked_list_create();
+}
+
+/**
+ * move a task of a specific type from the queue to the active list
+ */
+static bool activate_task(private_task_manager_t *this, task_type_t type)
+{
+ iterator_t *iterator;
+ task_t *task;
+ bool found = FALSE;
+
+ iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
+ while (iterator->iterate(iterator, (void**)&task))
+ {
+ if (task->get_type(task) == type)
+ {
+ DBG2(DBG_IKE, " activating %N task", task_type_names, type);
+ iterator->remove(iterator);
+ this->active_tasks->insert_last(this->active_tasks, task);
+ found = TRUE;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return found;
+}
+
+/**
+ * Implementation of task_manager_t.retransmit
+ */
+static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
+{
+ if (message_id == this->initiating.mid)
+ {
+ u_int32_t timeout;
+ job_t *job;
+ iterator_t *iterator;
+ packet_t *packet;
+ task_t *task;
+ ike_mobike_t *mobike = NULL;
+
+ /* check if we are retransmitting a MOBIKE routability check */
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ if (task->get_type(task) == IKE_MOBIKE)
+ {
+ mobike = (ike_mobike_t*)task;
+ if (!mobike->is_probing(mobike))
+ {
+ mobike = NULL;
+ }
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (mobike == NULL)
+ {
+ if (this->initiating.retransmitted <= this->retransmit_tries)
+ {
+ timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ pow(this->retransmit_base, this->initiating.retransmitted));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d retransmits",
+ this->initiating.retransmitted - 1);
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
+ this->initiating.retransmitted, message_id);
+ }
+ packet = this->initiating.packet->clone(this->initiating.packet);
+ charon->sender->send(charon->sender, packet);
+ }
+ else
+ { /* for routeability checks, we use a more aggressive behavior */
+ if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
+ {
+ timeout = ROUTEABILITY_CHECK_INTERVAL;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d path probings",
+ this->initiating.retransmitted - 1);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "path probing attempt %d",
+ this->initiating.retransmitted);
+ }
+ mobike->transmit(mobike, this->initiating.packet);
+ }
+
+ this->initiating.retransmitted++;
+ job = (job_t*)retransmit_job_create(this->initiating.mid,
+ this->ike_sa->get_id(this->ike_sa));
+ charon->scheduler->schedule_job_ms(charon->scheduler, job, timeout);
+ }
+ return SUCCESS;
+}
+
+/**
+ * build a request using the active task list
+ * Implementation of task_manager_t.initiate
+ */
+static status_t build_request(private_task_manager_t *this)
+{
+ iterator_t *iterator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ status_t status;
+ exchange_type_t exchange = 0;
+
+ if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
+ {
+ DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
+ /* do not initiate if we already have a message in the air */
+ return SUCCESS;
+ }
+
+ if (this->active_tasks->get_count(this->active_tasks) == 0)
+ {
+ DBG2(DBG_IKE, "activating new tasks");
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_CREATED:
+ activate_task(this, IKE_VENDOR);
+ if (activate_task(this, IKE_INIT))
+ {
+ this->initiating.mid = 0;
+ exchange = IKE_SA_INIT;
+ activate_task(this, IKE_NATD);
+ activate_task(this, IKE_CERT_PRE);
+#ifdef ME
+ /* this task has to be activated before the IKE_AUTHENTICATE
+ * task, because that task pregenerates the packet after
+ * which no payloads can be added to the message anymore.
+ */
+ activate_task(this, IKE_ME);
+#endif /* ME */
+ activate_task(this, IKE_AUTHENTICATE);
+ activate_task(this, IKE_CERT_POST);
+ activate_task(this, IKE_CONFIG);
+ activate_task(this, CHILD_CREATE);
+ activate_task(this, IKE_AUTH_LIFETIME);
+ activate_task(this, IKE_MOBIKE);
+ }
+ break;
+ case IKE_ESTABLISHED:
+ if (activate_task(this, CHILD_CREATE))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, CHILD_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, CHILD_REKEY))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, IKE_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, IKE_REKEY))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, IKE_REAUTH))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, IKE_MOBIKE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, IKE_DPD))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+#ifdef ME
+ if (activate_task(this, IKE_ME))
+ {
+ exchange = ME_CONNECT;
+ break;
+ }
+#endif /* ME */
+ case IKE_REKEYING:
+ if (activate_task(this, IKE_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ case IKE_DELETING:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ DBG2(DBG_IKE, "reinitiating already active tasks");
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void**)&task))
+ {
+ DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
+ switch (task->get_type(task))
+ {
+ case IKE_INIT:
+ exchange = IKE_SA_INIT;
+ break;
+ case IKE_AUTHENTICATE:
+ exchange = IKE_AUTH;
+ break;
+ case CHILD_CREATE:
+ case CHILD_REKEY:
+ case IKE_REKEY:
+ exchange = CREATE_CHILD_SA;
+ break;
+ case IKE_MOBIKE:
+ exchange = INFORMATIONAL;
+ default:
+ continue;
+ }
+ break;
+ }
+ iterator->destroy(iterator);
+ }
+
+ if (exchange == 0)
+ {
+ DBG2(DBG_IKE, "nothing to initiate");
+ /* nothing to do yet... */
+ return SUCCESS;
+ }
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+
+ message = message_create();
+ message->set_message_id(message, this->initiating.mid);
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_exchange_type(message, exchange);
+ this->initiating.type = exchange;
+ this->initiating.retransmitted = 0;
+
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ iterator->remove(iterator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ break;
+ case FAILED:
+ default:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ iterator->destroy(iterator);
+ message->destroy(message);
+ flush(this);
+ return DESTROY_ME;
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* update exchange type if a task changed it */
+ this->initiating.type = message->get_exchange_type(message);
+
+ charon->bus->message(charon->bus, message, FALSE);
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->initiating.packet);
+ if (status != SUCCESS)
+ {
+ /* message generation failed. There is nothing more to do than to
+ * close the SA */
+ message->destroy(message);
+ flush(this);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+ message->destroy(message);
+
+ return retransmit(this, this->initiating.mid);
+}
+
+/**
+ * handle an incoming response message
+ */
+static status_t process_response(private_task_manager_t *this,
+ message_t *message)
+{
+ iterator_t *iterator;
+ task_t *task;
+
+ if (message->get_exchange_type(message) != this->initiating.type)
+ {
+ DBG1(DBG_IKE, "received %N response, but expected %N",
+ exchange_type_names, message->get_exchange_type(message),
+ exchange_type_names, this->initiating.type);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ /* catch if we get resetted while processing */
+ this->reset = FALSE;
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ iterator->remove(iterator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ iterator->remove(iterator);
+ iterator->destroy(iterator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ if (this->reset)
+ { /* start all over again if we were reset */
+ this->reset = FALSE;
+ iterator->destroy(iterator);
+ return build_request(this);
+ }
+ }
+ iterator->destroy(iterator);
+
+ this->initiating.mid++;
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ this->initiating.packet->destroy(this->initiating.packet);
+ this->initiating.packet = NULL;
+
+ return build_request(this);
+}
+
+/**
+ * handle exchange collisions
+ */
+static void handle_collisions(private_task_manager_t *this, task_t *task)
+{
+ iterator_t *iterator;
+ task_t *active;
+ task_type_t type;
+
+ type = task->get_type(task);
+
+ /* do we have to check */
+ if (type == IKE_REKEY || type == CHILD_REKEY ||
+ type == CHILD_DELETE || type == IKE_DELETE || type == IKE_REAUTH)
+ {
+ /* find an exchange collision, and notify these tasks */
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void**)&active))
+ {
+ switch (active->get_type(active))
+ {
+ case IKE_REKEY:
+ if (type == IKE_REKEY || type == IKE_DELETE ||
+ type == IKE_REAUTH)
+ {
+ ike_rekey_t *rekey = (ike_rekey_t*)active;
+ rekey->collide(rekey, task);
+ break;
+ }
+ continue;
+ case CHILD_REKEY:
+ if (type == CHILD_REKEY || type == CHILD_DELETE)
+ {
+ child_rekey_t *rekey = (child_rekey_t*)active;
+ rekey->collide(rekey, task);
+ break;
+ }
+ continue;
+ default:
+ continue;
+ }
+ iterator->destroy(iterator);
+ return;
+ }
+ iterator->destroy(iterator);
+ }
+ /* destroy task if not registered in any active task */
+ task->destroy(task);
+}
+
+/**
+ * build a response depending on the "passive" task list
+ */
+static status_t build_response(private_task_manager_t *this, message_t *request)
+{
+ iterator_t *iterator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ bool delete = FALSE;
+ status_t status;
+
+ me = request->get_destination(request);
+ other = request->get_source(request);
+
+ message = message_create();
+ message->set_exchange_type(message, request->get_exchange_type(request));
+ /* send response along the path the request came in */
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_message_id(message, this->responding.mid);
+ message->set_request(message, FALSE);
+
+ iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ iterator->remove(iterator);
+ handle_collisions(this, task);
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* destroy IKE_SA, but SEND response first */
+ delete = TRUE;
+ break;
+ }
+ if (delete)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* remove resonder SPI if IKE_SA_INIT failed */
+ if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
+ {
+ ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
+ id->set_responder_spi(id, 0);
+ }
+
+ /* message complete, send it */
+ DESTROY_IF(this->responding.packet);
+ this->responding.packet = NULL;
+ charon->bus->message(charon->bus, message, FALSE);
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->responding.packet);
+ message->destroy(message);
+ if (status != SUCCESS)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ charon->sender->send(charon->sender,
+ this->responding.packet->clone(this->responding.packet));
+ if (delete)
+ {
+ return DESTROY_ME;
+ }
+ return SUCCESS;
+}
+
+/**
+ * handle an incoming request message
+ */
+static status_t process_request(private_task_manager_t *this,
+ message_t *message)
+{
+ enumerator_t *enumerator;
+ iterator_t *iterator;
+ task_t *task = NULL;
+ payload_t *payload;
+ notify_payload_t *notify;
+ delete_payload_t *delete;
+
+ if (this->passive_tasks->get_count(this->passive_tasks) == 0)
+ { /* create tasks depending on request type, if not already some queued */
+ switch (message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ {
+ task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+#ifdef ME
+ task = (task_t*)ike_me_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+#endif /* ME */
+ task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_config_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
+ NULL, NULL);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+ case CREATE_CHILD_SA:
+ { /* FIXME: we should prevent this on mediation connections */
+ bool notify_found = FALSE, ts_found = FALSE;
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY:
+ { /* if we find a rekey notify, its CHILD_SA rekeying */
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == REKEY_SA &&
+ (notify->get_protocol_id(notify) == PROTO_AH ||
+ notify->get_protocol_id(notify) == PROTO_ESP))
+ {
+ notify_found = TRUE;
+ }
+ break;
+ }
+ case TRAFFIC_SELECTOR_INITIATOR:
+ case TRAFFIC_SELECTOR_RESPONDER:
+ { /* if we don't find a TS, its IKE rekeying */
+ ts_found = TRUE;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ts_found)
+ {
+ if (notify_found)
+ {
+ task = (task_t*)child_rekey_create(this->ike_sa,
+ PROTO_NONE, 0);
+ }
+ else
+ {
+ task = (task_t*)child_create_create(this->ike_sa, NULL,
+ FALSE, NULL, NULL);
+ }
+ }
+ else
+ {
+ task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
+ }
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+ case INFORMATIONAL:
+ {
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY:
+ {
+ notify = (notify_payload_t*)payload;
+ switch (notify->get_notify_type(notify))
+ {
+ case ADDITIONAL_IP4_ADDRESS:
+ case ADDITIONAL_IP6_ADDRESS:
+ case NO_ADDITIONAL_ADDRESSES:
+ case UPDATE_SA_ADDRESSES:
+ case NO_NATS_ALLOWED:
+ case UNACCEPTABLE_ADDRESSES:
+ case UNEXPECTED_NAT_DETECTED:
+ case COOKIE2:
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ task = (task_t*)ike_mobike_create(
+ this->ike_sa, FALSE);
+ break;
+ case AUTH_LIFETIME:
+ task = (task_t*)ike_auth_lifetime_create(
+ this->ike_sa, FALSE);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case DELETE:
+ {
+ delete = (delete_payload_t*)payload;
+ if (delete->get_protocol_id(delete) == PROTO_IKE)
+ {
+ task = (task_t*)ike_delete_create(this->ike_sa,
+ FALSE);
+ }
+ else
+ {
+ task = (task_t*)child_delete_create(this->ike_sa,
+ PROTO_NONE, 0);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (task)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (task == NULL)
+ {
+ task = (task_t*)ike_dpd_create(FALSE);
+ }
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+#ifdef ME
+ case ME_CONNECT:
+ {
+ task = (task_t*)ike_me_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ }
+#endif /* ME */
+ default:
+ break;
+ }
+ }
+
+ /* let the tasks process the message */
+ iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ iterator->remove(iterator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs at least another call to build() */
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ iterator->remove(iterator);
+ iterator->destroy(iterator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return build_response(this, message);
+}
+
+/**
+ * Implementation of task_manager_t.process_message
+ */
+static status_t process_message(private_task_manager_t *this, message_t *msg)
+{
+ u_int32_t mid = msg->get_message_id(msg);
+
+ if (msg->get_request(msg))
+ {
+ if (mid == this->responding.mid)
+ {
+ charon->bus->message(charon->bus, msg, TRUE);
+ if (process_request(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ this->responding.mid++;
+ }
+ else if ((mid == this->responding.mid - 1) && this->responding.packet)
+ {
+ packet_t *clone;
+ host_t *me, *other;
+
+ DBG1(DBG_IKE, "received retransmit of request with ID %d, "
+ "retransmitting response", mid);
+ clone = this->responding.packet->clone(this->responding.packet);
+ me = msg->get_destination(msg);
+ other = msg->get_source(msg);
+ clone->set_source(clone, me->clone(me));
+ clone->set_destination(clone, other->clone(other));
+ charon->sender->send(charon->sender, clone);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ mid, this->responding.mid);
+ }
+ }
+ else
+ {
+ if (mid == this->initiating.mid)
+ {
+ charon->bus->message(charon->bus, msg, TRUE);
+ if (process_response(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ mid, this->initiating.mid);
+ return SUCCESS;
+ }
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_manager_t.queue_task
+ */
+static void queue_task(private_task_manager_t *this, task_t *task)
+{
+ if (task->get_type(task) == IKE_MOBIKE)
+ { /* there is no need to queue more than one mobike task */
+ iterator_t *iterator;
+ task_t *current;
+
+ iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current->get_type(current) == IKE_MOBIKE)
+ {
+ iterator->destroy(iterator);
+ task->destroy(task);
+ return;
+ }
+ }
+ iterator->destroy(iterator);
+ }
+ DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
+ this->queued_tasks->insert_last(this->queued_tasks, task);
+}
+
+/**
+ * Implementation of task_manager_t.adopt_tasks
+ */
+static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
+{
+ task_t *task;
+
+ /* move queued tasks from other to this */
+ while (other->queued_tasks->remove_last(other->queued_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+}
+
+/**
+ * Implementation of task_manager_t.busy
+ */
+static bool busy(private_task_manager_t *this)
+{
+ return (this->active_tasks->get_count(this->active_tasks) > 0);
+}
+
+/**
+ * Implementation of task_manager_t.reset
+ */
+static void reset(private_task_manager_t *this,
+ u_int32_t initiate, u_int32_t respond)
+{
+ task_t *task;
+
+ /* reset message counters and retransmit packets */
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ this->responding.packet = NULL;
+ this->initiating.packet = NULL;
+ if (initiate != UINT_MAX)
+ {
+ this->initiating.mid = initiate;
+ }
+ if (respond != UINT_MAX)
+ {
+ this->responding.mid = respond;
+ }
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+
+ /* reset active tasks */
+ while (this->active_tasks->remove_last(this->active_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+
+ this->reset = TRUE;
+}
+
+/**
+ * Implementation of task_manager_t.destroy
+ */
+static void destroy(private_task_manager_t *this)
+{
+ flush(this);
+
+ this->active_tasks->destroy(this->active_tasks);
+ this->queued_tasks->destroy(this->queued_tasks);
+ this->passive_tasks->destroy(this->passive_tasks);
+
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+task_manager_t *task_manager_create(ike_sa_t *ike_sa)
+{
+ private_task_manager_t *this = malloc_thing(private_task_manager_t);
+
+ this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
+ this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
+ this->public.initiate = (status_t(*)(task_manager_t*))build_request;
+ this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
+ this->public.reset = (void(*)(task_manager_t*,u_int32_t,u_int32_t))reset;
+ this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
+ this->public.busy = (bool(*)(task_manager_t*))busy;
+ this->public.destroy = (void(*)(task_manager_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->responding.packet = NULL;
+ this->initiating.packet = NULL;
+ this->responding.mid = 0;
+ this->initiating.mid = 0;
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ this->queued_tasks = linked_list_create();
+ this->active_tasks = linked_list_create();
+ this->passive_tasks = linked_list_create();
+ this->reset = FALSE;
+
+ this->retransmit_tries = lib->settings->get_int(lib->settings,
+ "charon.retransmit_tries", RETRANSMIT_TRIES);
+ this->retransmit_timeout = lib->settings->get_double(lib->settings,
+ "charon.retransmit_timeout", RETRANSMIT_TIMEOUT);
+ this->retransmit_base = lib->settings->get_double(lib->settings,
+ "charon.retransmit_base", RETRANSMIT_BASE);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
new file mode 100644
index 000000000..731ed4898
--- /dev/null
+++ b/src/libcharon/sa/task_manager.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2006 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 task_manager task_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef TASK_MANAGER_H_
+#define TASK_MANAGER_H_
+
+typedef struct task_manager_t task_manager_t;
+
+#include <limits.h>
+
+#include <library.h>
+#include <encoding/message.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * First retransmit timeout in seconds.
+ */
+#define RETRANSMIT_TIMEOUT 4.0
+
+/**
+ * Base which is raised to the power of the retransmission try.
+ */
+#define RETRANSMIT_BASE 1.8
+
+/**
+ * Number of retransmits done before giving up.
+ */
+#define RETRANSMIT_TRIES 5
+
+/**
+ * Interval for mobike routability checks in ms.
+ */
+#define ROUTEABILITY_CHECK_INTERVAL 2500
+
+/**
+ * Number of routability checks before giving up
+ */
+#define ROUTEABILITY_CHECK_TRIES 10
+
+
+/**
+ * The task manager, juggles task and handles message exchanges.
+ *
+ * On incoming requests, the task manager creates new tasks on demand and
+ * juggles the request through all available tasks. Each task inspects the
+ * request and adds payloads as necessary to the response.
+ * On outgoing requests, the task manager delivers the request through the tasks
+ * to build it, the response gets processed by each task to complete.
+ * The task manager has an internal Queue to store task which should get
+ * completed.
+ * For the initial IKE_SA setup, several tasks are queued: One for the
+ * unauthenticated IKE_SA setup, one for authentication, one for CHILD_SA setup
+ * and maybe one for virtual IP assignement.
+ * The task manager is also responsible for retransmission. It uses a backoff
+ * algorithm. The timeout is calculated using
+ * RETRANSMIT_TIMEOUT * (RETRANSMIT_BASE ** try).
+ * When try reaches RETRANSMIT_TRIES, retransmission is given up.
+ *
+ * Using an initial TIMEOUT of 4s, a BASE of 1.8, and 5 TRIES gives us:
+ * @verbatim
+ | relative | absolute
+ ---------------------------------------------------------
+ 4s * (1.8 ** 0) = 4s 4s
+ 4s * (1.8 ** 1) = 7s 11s
+ 4s * (1.8 ** 2) = 13s 24s
+ 4s * (1.8 ** 3) = 23s 47s
+ 4s * (1.8 ** 4) = 42s 89s
+ 4s * (1.8 ** 5) = 76s 165s
+
+ @endverbatim
+ * The peer is considered dead after 2min 45s when no reply comes in.
+ */
+struct task_manager_t {
+
+ /**
+ * Process an incoming message.
+ *
+ * @param message message to add payloads to
+ * @return
+ * - DESTROY_ME if IKE_SA must be closed
+ * - SUCCESS otherwise
+ */
+ status_t (*process_message) (task_manager_t *this, message_t *message);
+
+ /**
+ * Initiate an exchange with the currently queued tasks.
+ */
+ status_t (*initiate) (task_manager_t *this);
+
+ /**
+ * Queue a task in the manager.
+ *
+ * @param task task to queue
+ */
+ void (*queue_task) (task_manager_t *this, task_t *task);
+
+ /**
+ * Retransmit a request if it hasn't been acknowledged yet.
+ *
+ * A return value of INVALID_STATE means that the message was already
+ * acknowledged and has not to be retransmitted. A return value of SUCCESS
+ * means retransmission was required and the message has been resent.
+ *
+ * @param message_id ID of the message to retransmit
+ * @return
+ * - INVALID_STATE if retransmission not required
+ * - SUCCESS if retransmission sent
+ */
+ status_t (*retransmit) (task_manager_t *this, u_int32_t message_id);
+
+ /**
+ * Migrate all tasks from other to this.
+ *
+ * To rekey or reestablish an IKE_SA completely, all queued or active
+ * tasks should get migrated to the new IKE_SA.
+ *
+ * @param other manager which gives away its tasks
+ */
+ void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
+
+ /**
+ * Reset message ID counters of the task manager.
+ *
+ * The IKEv2 protocol requires to restart exchanges with message IDs
+ * reset to zero (INVALID_KE_PAYLOAD, COOKIES, ...). The reset() method
+ * resets the message IDs and resets all active tasks using the migrate()
+ * method.
+ * Use a value of UINT_MAX to keep the current message ID.
+ *
+ * @param initiate message ID to initiate exchanges (send)
+ * @param respond message ID to respond to exchanges (expect)
+ */
+ void (*reset) (task_manager_t *this, u_int32_t initiate, u_int32_t respond);
+
+ /**
+ * Check if we are currently waiting for a reply.
+ *
+ * @return TRUE if we are waiting, FALSE otherwise
+ */
+ bool (*busy) (task_manager_t *this);
+
+ /**
+ * Destroy the task_manager_t.
+ */
+ void (*destroy) (task_manager_t *this);
+};
+
+/**
+ * Create an instance of the task manager.
+ *
+ * @param ike_sa IKE_SA to manage.
+ */
+task_manager_t *task_manager_create(ike_sa_t *ike_sa);
+
+#endif /** TASK_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
new file mode 100644
index 000000000..bea4f73d5
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "child_create.h"
+
+#include <daemon.h>
+#include <crypto/diffie_hellman.h>
+#include <credentials/certificates/x509.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/inactivity_job.h>
+
+
+typedef struct private_child_create_t private_child_create_t;
+
+/**
+ * Private members of a child_create_t task.
+ */
+struct private_child_create_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ child_create_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * nonce chosen by us
+ */
+ chunk_t my_nonce;
+
+ /**
+ * nonce chosen by peer
+ */
+ chunk_t other_nonce;
+
+ /**
+ * config to create the CHILD_SA from
+ */
+ child_cfg_t *config;
+
+ /**
+ * list of proposal candidates
+ */
+ linked_list_t *proposals;
+
+ /**
+ * selected proposal to use for CHILD_SA
+ */
+ proposal_t *proposal;
+
+ /**
+ * traffic selectors for initiators side
+ */
+ linked_list_t *tsi;
+
+ /**
+ * traffic selectors for responders side
+ */
+ linked_list_t *tsr;
+
+ /**
+ * source of triggering packet
+ */
+ traffic_selector_t *packet_tsi;
+
+ /**
+ * destination of triggering packet
+ */
+ traffic_selector_t *packet_tsr;
+
+ /**
+ * optional diffie hellman exchange
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * group used for DH exchange
+ */
+ diffie_hellman_group_t dh_group;
+
+ /**
+ * IKE_SAs keymat
+ */
+ keymat_t *keymat;
+
+ /**
+ * mode the new CHILD_SA uses (transport/tunnel/beet)
+ */
+ ipsec_mode_t mode;
+
+ /**
+ * IPComp transform to use
+ */
+ ipcomp_transform_t ipcomp;
+
+ /**
+ * IPComp transform proposed or accepted by the other peer
+ */
+ ipcomp_transform_t ipcomp_received;
+
+ /**
+ * Own allocated SPI
+ */
+ u_int32_t my_spi;
+
+ /**
+ * SPI received in proposal
+ */
+ u_int32_t other_spi;
+
+ /**
+ * Own allocated Compression Parameter Index (CPI)
+ */
+ u_int16_t my_cpi;
+
+ /**
+ * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
+ */
+ u_int16_t other_cpi;
+
+ /**
+ * reqid to use if we are rekeying
+ */
+ u_int32_t reqid;
+
+ /**
+ * CHILD_SA which gets established
+ */
+ child_sa_t *child_sa;
+
+ /**
+ * successfully established the CHILD?
+ */
+ bool established;
+
+ /**
+ * whether the CHILD_SA rekeys an existing one
+ */
+ bool rekey;
+};
+
+/**
+ * get the nonce from a message
+ */
+static status_t get_nonce(message_t *message, chunk_t *nonce)
+{
+ nonce_payload_t *payload;
+
+ payload = (nonce_payload_t*)message->get_payload(message, NONCE);
+ if (payload == NULL)
+ {
+ return FAILED;
+ }
+ *nonce = payload->get_nonce(payload);
+ return NEED_MORE;
+}
+
+/**
+ * generate a new nonce to include in a CREATE_CHILD_SA message
+ */
+static status_t generate_nonce(chunk_t *nonce)
+{
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "error generating nonce value, no RNG found");
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, NONCE_SIZE, nonce);
+ rng->destroy(rng);
+ return SUCCESS;
+}
+
+/**
+ * Check a list of traffic selectors if any selector belongs to host
+ */
+static bool ts_list_is_host(linked_list_t *list, host_t *host)
+{
+ traffic_selector_t *ts;
+ bool is_host = TRUE;
+ iterator_t *iterator = list->create_iterator(list, TRUE);
+
+ while (is_host && iterator->iterate(iterator, (void**)&ts))
+ {
+ is_host = is_host && ts->is_host(ts, host);
+ }
+ iterator->destroy(iterator);
+ return is_host;
+}
+
+/**
+ * Allocate SPIs and update proposals
+ */
+static bool allocate_spi(private_child_create_t *this)
+{
+ enumerator_t *enumerator;
+ proposal_t *proposal;
+
+ /* TODO: allocate additional SPI for AH if we have such proposals */
+ this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+ if (this->my_spi)
+ {
+ if (this->initiator)
+ {
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ proposal->set_spi(proposal, this->my_spi);
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ this->proposal->set_spi(this->proposal, this->my_spi);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
+ */
+static void schedule_inactivity_timeout(private_child_create_t *this)
+{
+ u_int32_t timeout;
+ bool close_ike;
+
+ timeout = this->config->get_inactivity(this->config);
+ if (timeout)
+ {
+ close_ike = lib->settings->get_bool(lib->settings,
+ "charon.inactivity_close_ike", FALSE);
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)
+ inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
+ timeout, close_ike), timeout);
+ }
+}
+
+/**
+ * Install a CHILD_SA for usage, return value:
+ * - FAILED: no acceptable proposal
+ * - INVALID_ARG: diffie hellman group inacceptable
+ * - NOT_FOUND: TS inacceptable
+ */
+static status_t select_and_install(private_child_create_t *this, bool no_dh)
+{
+ status_t status, status_i, status_o;
+ chunk_t nonce_i, nonce_r;
+ chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
+ chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
+ linked_list_t *my_ts, *other_ts;
+ host_t *me, *other, *other_vip, *my_vip;
+ bool private;
+
+ if (this->proposals == NULL)
+ {
+ DBG1(DBG_IKE, "SA payload missing in message");
+ return FAILED;
+ }
+ if (this->tsi == NULL || this->tsr == NULL)
+ {
+ DBG1(DBG_IKE, "TS payloads missing in message");
+ return NOT_FOUND;
+ }
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
+
+ private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
+ this->proposal = this->config->select_proposal(this->config,
+ this->proposals, no_dh, private);
+ if (this->proposal == NULL)
+ {
+ DBG1(DBG_IKE, "no acceptable proposal found");
+ return FAILED;
+ }
+ this->other_spi = this->proposal->get_spi(this->proposal);
+
+ if (!this->initiator && !allocate_spi(this))
+ { /* responder has no SPI allocated yet */
+ DBG1(DBG_IKE, "allocating SPI failed");
+ return FAILED;
+ }
+ this->child_sa->set_proposal(this->child_sa, this->proposal);
+
+ if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
+ {
+ u_int16_t group;
+
+ if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
+ &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
+ diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
+ this->dh_group = group;
+ return INVALID_ARG;
+ }
+ /* the selected proposal does not use a DH group */
+ DBG1(DBG_IKE, "ignoring KE exchange, agreed on a non-PFS proposal");
+ DESTROY_IF(this->dh);
+ this->dh = NULL;
+ this->dh_group = MODP_NONE;
+ }
+
+ if (my_vip == NULL)
+ {
+ my_vip = me;
+ }
+ if (other_vip == NULL)
+ {
+ other_vip = other;
+ }
+
+ if (this->initiator)
+ {
+ nonce_i = this->my_nonce;
+ nonce_r = this->other_nonce;
+ my_ts = this->tsi;
+ other_ts = this->tsr;
+ }
+ else
+ {
+ nonce_r = this->my_nonce;
+ nonce_i = this->other_nonce;
+ my_ts = this->tsr;
+ other_ts = this->tsi;
+ }
+ my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
+ my_vip);
+ other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
+ other_vip);
+
+ if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
+ {
+ my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
+ DBG1(DBG_IKE, "no acceptable traffic selectors found");
+ return NOT_FOUND;
+ }
+
+ this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
+ this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
+ if (this->initiator)
+ {
+ this->tsi = my_ts;
+ this->tsr = other_ts;
+ }
+ else
+ {
+ this->tsr = my_ts;
+ this->tsi = other_ts;
+ }
+
+ if (!this->initiator)
+ {
+ /* check if requested mode is acceptable, downgrade if required */
+ switch (this->mode)
+ {
+ case MODE_TRANSPORT:
+ if (!this->config->use_proxy_mode(this->config) &&
+ (!ts_list_is_host(this->tsi, other) ||
+ !ts_list_is_host(this->tsr, me))
+ )
+ {
+ this->mode = MODE_TUNNEL;
+ DBG1(DBG_IKE, "not using transport mode, not host-to-host");
+ }
+ else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ this->mode = MODE_TUNNEL;
+ DBG1(DBG_IKE, "not using transport mode, connection NATed");
+ }
+ break;
+ case MODE_BEET:
+ if (!ts_list_is_host(this->tsi, NULL) ||
+ !ts_list_is_host(this->tsr, NULL))
+ {
+ this->mode = MODE_TUNNEL;
+ DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* check for any certificate-based IP address block constraints */
+ if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL)
+ {
+ auth_cfg_t *auth;
+ enumerator_t *auth_enum;
+ certificate_t *cert = NULL;
+
+ auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
+ while (auth_enum->enumerate(auth_enum, &auth))
+ {
+ cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
+ if (cert)
+ {
+ break;
+ }
+ }
+ auth_enum->destroy(auth_enum);
+
+ if (cert && cert->get_type(cert) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+ {
+ enumerator_t *enumerator, *block_enum;
+ traffic_selector_t *ts, *block_ts;
+
+ DBG1(DBG_IKE, "checking certificate-based traffic selector "
+ "constraints [RFC 3779]");
+ enumerator = other_ts->create_enumerator(other_ts);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ bool contained = FALSE;
+
+ block_enum = x509->create_ipAddrBlock_enumerator(x509);
+ while (block_enum->enumerate(block_enum, &block_ts))
+ {
+ if (ts->is_contained_in(ts, block_ts))
+ {
+ DBG1(DBG_IKE, " TS %R is contained in address block"
+ " constraint %R", ts, block_ts);
+ contained = TRUE;
+ break;
+ }
+ }
+ block_enum->destroy(block_enum);
+
+ if (!contained)
+ {
+ DBG1(DBG_IKE, " TS %R is not contained in any"
+ " address block constraint", ts);
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ }
+
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+ this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
+ this->child_sa->set_mode(this->child_sa, this->mode);
+ this->child_sa->set_protocol(this->child_sa,
+ this->proposal->get_protocol(this->proposal));
+
+ if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
+ {
+ this->my_cpi = this->other_cpi = 0;
+ this->ipcomp = IPCOMP_NONE;
+ }
+ status_i = status_o = FAILED;
+ if (this->keymat->derive_child_keys(this->keymat, this->proposal,
+ this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ {
+ if (this->initiator)
+ {
+ status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
+ status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
+ this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+ }
+ else
+ {
+ status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
+ this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
+ status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+ }
+ }
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
+
+ if (status_i != SUCCESS || status_o != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
+ (status_i != SUCCESS) ? "inbound " : "",
+ (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
+ (status_o != SUCCESS) ? "outbound " : "");
+ return FAILED;
+ }
+
+ status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
+ return NOT_FOUND;
+ }
+
+ charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
+ nonce_i, nonce_r);
+
+ /* add to IKE_SA, and remove from task */
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
+ this->established = TRUE;
+
+ if (!this->rekey)
+ { /* a rekeyed SA uses the same reqid, no need for a new job */
+ schedule_inactivity_timeout(this);
+ }
+ return SUCCESS;
+}
+
+/**
+ * build the payloads for the message
+ */
+static void build_payloads(private_child_create_t *this, message_t *message)
+{
+ sa_payload_t *sa_payload;
+ nonce_payload_t *nonce_payload;
+ ke_payload_t *ke_payload;
+ ts_payload_t *ts_payload;
+
+ /* add SA payload */
+ if (this->initiator)
+ {
+ sa_payload = sa_payload_create_from_proposal_list(this->proposals);
+ }
+ else
+ {
+ sa_payload = sa_payload_create_from_proposal(this->proposal);
+ }
+ message->add_payload(message, (payload_t*)sa_payload);
+
+ /* add nonce payload if not in IKE_AUTH */
+ if (message->get_exchange_type(message) == CREATE_CHILD_SA)
+ {
+ nonce_payload = nonce_payload_create();
+ nonce_payload->set_nonce(nonce_payload, this->my_nonce);
+ message->add_payload(message, (payload_t*)nonce_payload);
+ }
+
+ /* diffie hellman exchange, if PFS enabled */
+ if (this->dh)
+ {
+ ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
+ message->add_payload(message, (payload_t*)ke_payload);
+ }
+
+ /* add TSi/TSr payloads */
+ ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
+ message->add_payload(message, (payload_t*)ts_payload);
+ ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
+ message->add_payload(message, (payload_t*)ts_payload);
+
+ /* add a notify if we are not in tunnel mode */
+ switch (this->mode)
+ {
+ case MODE_TRANSPORT:
+ message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
+ break;
+ case MODE_BEET:
+ message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
+ */
+static void add_ipcomp_notify(private_child_create_t *this,
+ message_t *message, u_int8_t ipcomp)
+{
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
+ "IPComp disabled");
+ return;
+ }
+
+ this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
+ if (this->my_cpi)
+ {
+ this->ipcomp = ipcomp;
+ message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
+ chunk_cata("cc", chunk_from_thing(this->my_cpi),
+ chunk_from_thing(ipcomp)));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
+ }
+}
+
+/**
+ * handle a received notify payload
+ */
+static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
+{
+ switch (notify->get_notify_type(notify))
+ {
+ case USE_TRANSPORT_MODE:
+ this->mode = MODE_TRANSPORT;
+ break;
+ case USE_BEET_MODE:
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+ { /* handle private use notify only if we know its meaning */
+ this->mode = MODE_BEET;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received a notify strongSwan uses for BEET "
+ "mode, but peer implementation unknown, skipped");
+ }
+ break;
+ case IPCOMP_SUPPORTED:
+ {
+ ipcomp_transform_t ipcomp;
+ u_int16_t cpi;
+ chunk_t data;
+
+ data = notify->get_notification_data(notify);
+ cpi = *(u_int16_t*)data.ptr;
+ ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
+ switch (ipcomp)
+ {
+ case IPCOMP_DEFLATE:
+ this->other_cpi = cpi;
+ this->ipcomp_received = ipcomp;
+ break;
+ case IPCOMP_LZS:
+ case IPCOMP_LZJH:
+ default:
+ DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
+ "transform ID we don't support %N",
+ ipcomp_transform_names, ipcomp);
+ break;
+ }
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Read payloads from message
+ */
+static void process_payloads(private_child_create_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ sa_payload_t *sa_payload;
+ ke_payload_t *ke_payload;
+ ts_payload_t *ts_payload;
+
+ /* defaults to TUNNEL mode */
+ this->mode = MODE_TUNNEL;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case SECURITY_ASSOCIATION:
+ sa_payload = (sa_payload_t*)payload;
+ this->proposals = sa_payload->get_proposals(sa_payload);
+ break;
+ case KEY_EXCHANGE:
+ ke_payload = (ke_payload_t*)payload;
+ if (!this->initiator)
+ {
+ this->dh_group = ke_payload->get_dh_group_number(ke_payload);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ }
+ if (this->dh)
+ {
+ this->dh->set_other_public_value(this->dh,
+ ke_payload->get_key_exchange_data(ke_payload));
+ }
+ break;
+ case TRAFFIC_SELECTOR_INITIATOR:
+ ts_payload = (ts_payload_t*)payload;
+ this->tsi = ts_payload->get_traffic_selectors(ts_payload);
+ break;
+ case TRAFFIC_SELECTOR_RESPONDER:
+ ts_payload = (ts_payload_t*)payload;
+ this->tsr = ts_payload->get_traffic_selectors(ts_payload);
+ break;
+ case NOTIFY:
+ handle_notify(this, (notify_payload_t*)payload);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_child_create_t *this, message_t *message)
+{
+ host_t *me, *other, *vip;
+ peer_cfg_t *peer_cfg;
+
+ switch (message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ return get_nonce(message, &this->my_nonce);
+ case CREATE_CHILD_SA:
+ if (generate_nonce(&this->my_nonce) != SUCCESS)
+ {
+ message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ return SUCCESS;
+ }
+ if (this->dh_group == MODP_NONE)
+ {
+ this->dh_group = this->config->get_dh_group(this->config);
+ }
+ break;
+ case IKE_AUTH:
+ if (message->get_message_id(message) != 1)
+ {
+ /* send only in the first request, not in subsequent rounds */
+ return NEED_MORE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (this->reqid)
+ {
+ DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
+ this->config->get_name(this->config), this->reqid);
+ }
+ else
+ {
+ DBG0(DBG_IKE, "establishing CHILD_SA %s",
+ this->config->get_name(this->config));
+ }
+
+ /* reuse virtual IP if we already have one */
+ me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (me == NULL)
+ {
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ }
+ other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
+ if (other == NULL)
+ {
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ }
+
+ /* check if we want a virtual IP, but don't have one */
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ vip = peer_cfg->get_virtual_ip(peer_cfg);
+ if (!this->reqid && vip)
+ {
+ /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
+ vip = host_create_any(vip->get_family(vip));
+ this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
+ NULL, vip);
+ vip->destroy(vip);
+ }
+ else
+ { /* but narrow it for host2host / if we already have a vip */
+ this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
+ NULL, me);
+ }
+ this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
+ NULL, other);
+
+ if (this->packet_tsi)
+ {
+ this->tsi->insert_first(this->tsi,
+ this->packet_tsi->clone(this->packet_tsi));
+ }
+ if (this->packet_tsr)
+ {
+ this->tsr->insert_first(this->tsr,
+ this->packet_tsr->clone(this->packet_tsr));
+ }
+ this->proposals = this->config->get_proposals(this->config,
+ this->dh_group == MODP_NONE);
+ this->mode = this->config->get_mode(this->config);
+ if (this->mode == MODE_TRANSPORT &&
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ this->mode = MODE_TUNNEL;
+ DBG1(DBG_IKE, "not using transport mode, connection NATed");
+ }
+
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+
+ if (!allocate_spi(this))
+ {
+ DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
+ return FAILED;
+ }
+
+ if (this->dh_group != MODP_NONE)
+ {
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ }
+
+ if (this->config->use_ipcomp(this->config))
+ {
+ /* IPCOMP_DEFLATE is the only transform we support at the moment */
+ add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
+ }
+
+ build_payloads(this, message);
+
+ this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
+ this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
+ this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
+ this->tsi = NULL;
+ this->tsr = NULL;
+ this->proposals = NULL;
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_child_create_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ return get_nonce(message, &this->other_nonce);
+ case CREATE_CHILD_SA:
+ get_nonce(message, &this->other_nonce);
+ break;
+ case IKE_AUTH:
+ if (message->get_message_id(message) != 1)
+ {
+ /* only handle first AUTH payload, not additional rounds */
+ return NEED_MORE;
+ }
+ default:
+ break;
+ }
+
+ process_payloads(this, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * handle CHILD_SA setup failure
+ */
+static void handle_child_sa_failure(private_child_create_t *this,
+ message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ lib->settings->get_bool(lib->settings,
+ "charon.close_ike_on_child_failure", FALSE))
+ {
+ /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
+ * first */
+ DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
+ charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
+ delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
+ 100);
+ }
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_child_create_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+ payload_t *payload;
+ enumerator_t *enumerator;
+ bool no_dh = TRUE;
+
+ switch (message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ return get_nonce(message, &this->my_nonce);
+ case CREATE_CHILD_SA:
+ if (generate_nonce(&this->my_nonce) != SUCCESS)
+ {
+ message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
+ chunk_empty);
+ return SUCCESS;
+ }
+ no_dh = FALSE;
+ break;
+ case IKE_AUTH:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
+ return NEED_MORE;
+ }
+ default:
+ break;
+ }
+
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
+ {
+ DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
+ message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
+ return SUCCESS;
+ }
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg && this->tsi && this->tsr)
+ {
+ host_t *me, *other;
+
+ me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (me == NULL)
+ {
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ }
+ other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
+ if (other == NULL)
+ {
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
+ this->tsi, me, other);
+ }
+
+ if (this->config == NULL)
+ {
+ DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
+ this->tsr, this->tsi);
+ message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+
+ /* check if ike_config_t included non-critical error notifies */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ switch (notify->get_notify_type(notify))
+ {
+ case INTERNAL_ADDRESS_FAILURE:
+ case FAILED_CP_REQUIRED:
+ {
+ DBG1(DBG_IKE,"configuration payload negotation "
+ "failed, no CHILD_SA built");
+ enumerator->destroy(enumerator);
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+
+ if (this->ipcomp_received != IPCOMP_NONE)
+ {
+ if (this->config->use_ipcomp(this->config))
+ {
+ add_ipcomp_notify(this, message, this->ipcomp_received);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
+ notify_type_names, IPCOMP_SUPPORTED);
+ }
+ }
+
+ switch (select_and_install(this, no_dh))
+ {
+ case SUCCESS:
+ break;
+ case NOT_FOUND:
+ message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ case INVALID_ARG:
+ {
+ u_int16_t group = htons(this->dh_group);
+ message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
+ chunk_from_thing(group));
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+ case FAILED:
+ default:
+ message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+
+ build_payloads(this, message);
+
+ DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+
+ if (!this->rekey)
+ { /* invoke the child_up() hook if we are not rekeying */
+ charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_child_create_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool no_dh = TRUE;
+
+ switch (message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ return get_nonce(message, &this->other_nonce);
+ case CREATE_CHILD_SA:
+ get_nonce(message, &this->other_nonce);
+ no_dh = FALSE;
+ break;
+ case IKE_AUTH:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
+ return NEED_MORE;
+ }
+ default:
+ break;
+ }
+
+ /* check for erronous notifies */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ /* handle notify errors related to CHILD_SA only */
+ case NO_PROPOSAL_CHOSEN:
+ case SINGLE_PAIR_REQUIRED:
+ case NO_ADDITIONAL_SAS:
+ case INTERNAL_ADDRESS_FAILURE:
+ case FAILED_CP_REQUIRED:
+ case TS_UNACCEPTABLE:
+ case INVALID_SELECTORS:
+ {
+ DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
+ notify_type_names, type);
+ enumerator->destroy(enumerator);
+ handle_child_sa_failure(this, message);
+ /* an error in CHILD_SA creation is not critical */
+ return SUCCESS;
+ }
+ case INVALID_KE_PAYLOAD:
+ {
+ chunk_t data;
+ u_int16_t group = MODP_NONE;
+
+ data = notify->get_notification_data(notify);
+ if (data.len == sizeof(group))
+ {
+ memcpy(&group, data.ptr, data.len);
+ group = ntohs(group);
+ }
+ DBG1(DBG_IKE, "peer didn't accept DH group %N, "
+ "it requested %N", diffie_hellman_group_names,
+ this->dh_group, diffie_hellman_group_names, group);
+ this->dh_group = group;
+ this->public.task.migrate(&this->public.task, this->ike_sa);
+ enumerator->destroy(enumerator);
+ return NEED_MORE;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ process_payloads(this, message);
+
+ if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
+ {
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
+ " one, no CHILD_SA built");
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+ else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
+ {
+ DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
+ "IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ }
+ else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
+ {
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
+ "no CHILD_SA built");
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+
+ if (select_and_install(this, no_dh) == SUCCESS)
+ {
+ DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+
+ if (!this->rekey)
+ { /* invoke the child_up() hook if we are not rekeying */
+ charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
+ }
+ }
+ else
+ {
+ handle_child_sa_failure(this, message);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_child_create_t *this)
+{
+ return CHILD_CREATE;
+}
+
+/**
+ * Implementation of child_create_t.use_reqid
+ */
+static void use_reqid(private_child_create_t *this, u_int32_t reqid)
+{
+ this->reqid = reqid;
+}
+
+/**
+ * Implementation of child_create_t.get_child
+ */
+static child_sa_t* get_child(private_child_create_t *this)
+{
+ return this->child_sa;
+}
+
+/**
+ * Implementation of child_create_t.get_lower_nonce
+ */
+static chunk_t get_lower_nonce(private_child_create_t *this)
+{
+ if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
+ min(this->my_nonce.len, this->other_nonce.len)) < 0)
+ {
+ return this->my_nonce;
+ }
+ else
+ {
+ return this->other_nonce;
+ }
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
+{
+ chunk_free(&this->my_nonce);
+ chunk_free(&this->other_nonce);
+ if (this->tsi)
+ {
+ this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
+ }
+ if (this->tsr)
+ {
+ this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
+ }
+ DESTROY_IF(this->child_sa);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->dh);
+ if (this->proposals)
+ {
+ this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
+ }
+
+ this->ike_sa = ike_sa;
+ this->keymat = ike_sa->get_keymat(ike_sa);
+ this->proposal = NULL;
+ this->proposals = NULL;
+ this->tsi = NULL;
+ this->tsr = NULL;
+ this->dh = NULL;
+ this->child_sa = NULL;
+ this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->other_cpi = 0;
+ this->reqid = 0;
+ this->established = FALSE;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_child_create_t *this)
+{
+ chunk_free(&this->my_nonce);
+ chunk_free(&this->other_nonce);
+ if (this->tsr)
+ {
+ this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
+ }
+ if (this->tsi)
+ {
+ this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
+ }
+ if (!this->established)
+ {
+ DESTROY_IF(this->child_sa);
+ }
+ DESTROY_IF(this->packet_tsi);
+ DESTROY_IF(this->packet_tsr);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->dh);
+ if (this->proposals)
+ {
+ this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
+ }
+
+ DESTROY_IF(this->config);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+child_create_t *child_create_create(ike_sa_t *ike_sa,
+ child_cfg_t *config, bool rekey,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
+{
+ private_child_create_t *this = malloc_thing(private_child_create_t);
+
+ this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
+ this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
+ this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+ if (config)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->initiator = TRUE;
+ config->get_ref(config);
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->initiator = FALSE;
+ }
+
+ this->ike_sa = ike_sa;
+ this->config = config;
+ this->my_nonce = chunk_empty;
+ this->other_nonce = chunk_empty;
+ this->proposals = NULL;
+ this->proposal = NULL;
+ this->tsi = NULL;
+ this->tsr = NULL;
+ this->packet_tsi = tsi ? tsi->clone(tsi) : NULL;
+ this->packet_tsr = tsr ? tsr->clone(tsr) : NULL;
+ this->dh = NULL;
+ this->dh_group = MODP_NONE;
+ this->keymat = ike_sa->get_keymat(ike_sa);
+ this->child_sa = NULL;
+ this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->my_spi = 0;
+ this->other_spi = 0;
+ this->my_cpi = 0;
+ this->other_cpi = 0;
+ this->reqid = 0;
+ this->established = FALSE;
+ this->rekey = rekey;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/child_create.h b/src/libcharon/sa/tasks/child_create.h
new file mode 100644
index 000000000..5dedeb8b1
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_create.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup child_create child_create
+ * @{ @ingroup tasks
+ */
+
+#ifndef CHILD_CREATE_H_
+#define CHILD_CREATE_H_
+
+typedef struct child_create_t child_create_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+#include <config/child_cfg.h>
+
+/**
+ * Task of type CHILD_CREATE, established a new CHILD_SA.
+ *
+ * This task may be included in the IKE_AUTH message or in a separate
+ * CREATE_CHILD_SA exchange.
+ */
+struct child_create_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Use a specific reqid for the CHILD_SA.
+ *
+ * When this task is used for rekeying, the same reqid is used
+ * for the new CHILD_SA.
+ *
+ * @param reqid reqid to use
+ */
+ void (*use_reqid) (child_create_t *this, u_int32_t reqid);
+
+ /**
+ * Get the lower of the two nonces, used for rekey collisions.
+ *
+ * @return lower nonce
+ */
+ chunk_t (*get_lower_nonce) (child_create_t *this);
+
+ /**
+ * Get the CHILD_SA established/establishing by this task.
+ *
+ * @return child_sa
+ */
+ child_sa_t* (*get_child) (child_create_t *this);
+};
+
+/**
+ * Create a new child_create task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param config child_cfg if task initiator, NULL if responder
+ * @param rekey whether we do a rekey or not
+ * @param tsi source of triggering packet, or NULL
+ * @param tsr destination of triggering packet, or NULL
+ * @return child_create task to handle by the task_manager
+ */
+child_create_t *child_create_create(ike_sa_t *ike_sa,
+ child_cfg_t *config, bool rekey,
+ traffic_selector_t *tsi, traffic_selector_t *tsr);
+
+#endif /** CHILD_CREATE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c
new file mode 100644
index 000000000..d7c6b0541
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_delete.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2006-2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "child_delete.h"
+
+#include <daemon.h>
+#include <encoding/payloads/delete_payload.h>
+
+
+typedef struct private_child_delete_t private_child_delete_t;
+
+/**
+ * Private members of a child_delete_t task.
+ */
+struct private_child_delete_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ child_delete_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Protocol of CHILD_SA to delete
+ */
+ protocol_id_t protocol;
+
+ /**
+ * Inbound SPI of CHILD_SA to delete
+ */
+ u_int32_t spi;
+
+ /**
+ * whether to enforce delete action policy
+ */
+ bool check_delete_action;
+
+ /**
+ * is this delete exchange following a rekey?
+ */
+ bool rekeyed;
+
+ /**
+ * CHILD_SAs which get deleted
+ */
+ linked_list_t *child_sas;
+};
+
+/**
+ * build the delete payloads from the listed child_sas
+ */
+static void build_payloads(private_child_delete_t *this, message_t *message)
+{
+ delete_payload_t *ah = NULL, *esp = NULL;
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ protocol_id_t protocol = child_sa->get_protocol(child_sa);
+ u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
+
+ switch (protocol)
+ {
+ case PROTO_ESP:
+ if (esp == NULL)
+ {
+ esp = delete_payload_create(PROTO_ESP);
+ message->add_payload(message, (payload_t*)esp);
+ }
+ esp->add_spi(esp, spi);
+ DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(spi));
+ break;
+ case PROTO_AH:
+ if (ah == NULL)
+ {
+ ah = delete_payload_create(PROTO_AH);
+ message->add_payload(message, (payload_t*)ah);
+ }
+ ah->add_spi(ah, spi);
+ DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(spi));
+ break;
+ default:
+ break;
+ }
+ child_sa->set_state(child_sa, CHILD_DELETING);
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * read in payloads and find the children to delete
+ */
+static void process_payloads(private_child_delete_t *this, message_t *message)
+{
+ enumerator_t *payloads;
+ iterator_t *spis;
+ payload_t *payload;
+ delete_payload_t *delete_payload;
+ u_int32_t *spi;
+ protocol_id_t protocol;
+ child_sa_t *child_sa;
+
+ payloads = message->create_payload_enumerator(message);
+ while (payloads->enumerate(payloads, &payload))
+ {
+ if (payload->get_type(payload) == DELETE)
+ {
+ delete_payload = (delete_payload_t*)payload;
+ protocol = delete_payload->get_protocol_id(delete_payload);
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ continue;
+ }
+ spis = delete_payload->create_spi_iterator(delete_payload);
+ while (spis->iterate(spis, (void**)&spi))
+ {
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
+ *spi, FALSE);
+ if (child_sa == NULL)
+ {
+ DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, "
+ "but no such SA", protocol_id_names, protocol, ntohl(*spi));
+ continue;
+ }
+ DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(*spi));
+
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_REKEYING:
+ this->rekeyed = TRUE;
+ /* we reply as usual, rekeying will fail */
+ break;
+ case CHILD_DELETING:
+ /* we don't send back a delete if we initiated ourself */
+ if (!this->initiator)
+ {
+ this->ike_sa->destroy_child_sa(this->ike_sa,
+ protocol, *spi);
+ continue;
+ }
+ case CHILD_INSTALLED:
+ if (!this->initiator)
+ { /* reestablish installed children if required */
+ this->check_delete_action = TRUE;
+ }
+ default:
+ break;
+ }
+
+ this->child_sas->insert_last(this->child_sas, child_sa);
+ }
+ spis->destroy(spis);
+ }
+ }
+ payloads->destroy(payloads);
+}
+
+/**
+ * destroy the children listed in this->child_sas, reestablish by policy
+ */
+static status_t destroy_and_reestablish(private_child_delete_t *this)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ child_cfg_t *child_cfg;
+ protocol_id_t protocol;
+ u_int32_t spi;
+ status_t status = SUCCESS;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ /* signal child down event if we are not rekeying */
+ if (!this->rekeyed)
+ {
+ charon->bus->child_updown(charon->bus, child_sa, FALSE);
+ }
+ spi = child_sa->get_spi(child_sa, TRUE);
+ protocol = child_sa->get_protocol(child_sa);
+ child_cfg = child_sa->get_config(child_sa);
+ child_cfg->get_ref(child_cfg);
+ this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
+ if (this->check_delete_action)
+ { /* enforce child_cfg policy if deleted passively */
+ switch (child_cfg->get_close_action(child_cfg))
+ {
+ case ACTION_RESTART:
+ child_cfg->get_ref(child_cfg);
+ status = this->ike_sa->initiate(this->ike_sa, child_cfg, 0,
+ NULL, NULL);
+ break;
+ case ACTION_ROUTE:
+ charon->traps->install(charon->traps,
+ this->ike_sa->get_peer_cfg(this->ike_sa), child_cfg);
+ break;
+ default:
+ break;
+ }
+ }
+ child_cfg->destroy(child_cfg);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return status;
+}
+
+/**
+ * send closing signals for all CHILD_SAs over the bus
+ */
+static void log_children(private_child_delete_t *this)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ u_int64_t bytes_in, bytes_out;
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
+ child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
+
+ DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
+ "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
+ ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_child_delete_t *this, message_t *message)
+{
+ child_sa_t *child_sa;
+
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
+ this->spi, TRUE);
+ if (!child_sa)
+ { /* check if it is an outbound sa */
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
+ this->spi, FALSE);
+ if (!child_sa)
+ { /* child does not exist anymore */
+ return SUCCESS;
+ }
+ /* we work only with the inbound SPI */
+ this->spi = child_sa->get_spi(child_sa, TRUE);
+ }
+ this->child_sas->insert_last(this->child_sas, child_sa);
+ if (child_sa->get_state(child_sa) == CHILD_REKEYING)
+ {
+ this->rekeyed = TRUE;
+ }
+ log_children(this);
+ build_payloads(this, message);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_child_delete_t *this, message_t *message)
+{
+ /* flush the list before adding new SAs */
+ this->child_sas->destroy(this->child_sas);
+ this->child_sas = linked_list_create();
+
+ process_payloads(this, message);
+ DBG1(DBG_IKE, "CHILD_SA closed");
+ return destroy_and_reestablish(this);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_r(private_child_delete_t *this, message_t *message)
+{
+ process_payloads(this, message);
+ log_children(this);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_child_delete_t *this, message_t *message)
+{
+ /* if we are rekeying, we send an empty informational */
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_REKEYING)
+ {
+ build_payloads(this, message);
+ }
+ DBG1(DBG_IKE, "CHILD_SA closed");
+ return destroy_and_reestablish(this);
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_child_delete_t *this)
+{
+ return CHILD_DELETE;
+}
+
+/**
+ * Implementation of child_delete_t.get_child
+ */
+static child_sa_t* get_child(private_child_delete_t *this)
+{
+ child_sa_t *child_sa = NULL;
+ this->child_sas->get_first(this->child_sas, (void**)&child_sa);
+ return child_sa;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa)
+{
+ this->check_delete_action = FALSE;
+ this->ike_sa = ike_sa;
+
+ this->child_sas->destroy(this->child_sas);
+ this->child_sas = linked_list_create();
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_child_delete_t *this)
+{
+ this->child_sas->destroy(this->child_sas);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi)
+{
+ private_child_delete_t *this = malloc_thing(private_child_delete_t);
+
+ this->public.get_child = (child_sa_t*(*)(child_delete_t*))get_child;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->check_delete_action = FALSE;
+ this->child_sas = linked_list_create();
+ this->protocol = protocol;
+ this->spi = spi;
+ this->rekeyed = FALSE;
+
+ if (protocol != PROTO_NONE)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->initiator = TRUE;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->initiator = FALSE;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/child_delete.h b/src/libcharon/sa/tasks/child_delete.h
new file mode 100644
index 000000000..365807c68
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_delete.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup child_delete child_delete
+ * @{ @ingroup tasks
+ */
+
+#ifndef CHILD_DELETE_H_
+#define CHILD_DELETE_H_
+
+typedef struct child_delete_t child_delete_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+#include <sa/child_sa.h>
+
+/**
+ * Task of type child_delete, delete a CHILD_SA.
+ */
+struct child_delete_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Get the CHILD_SA to delete by this task.
+ *
+ * @return child_sa
+ */
+ child_sa_t* (*get_child) (child_delete_t *this);
+};
+
+/**
+ * Create a new child_delete task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder
+ * @param spi inbound SPI of CHILD_SA to delete
+ * @return child_delete task to handle by the task_manager
+ */
+child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi);
+
+#endif /** CHILD_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
new file mode 100644
index 000000000..b5e4e84b4
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "child_rekey.h"
+
+#include <daemon.h>
+#include <encoding/payloads/notify_payload.h>
+#include <sa/tasks/child_create.h>
+#include <sa/tasks/child_delete.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+
+
+typedef struct private_child_rekey_t private_child_rekey_t;
+
+/**
+ * Private members of a child_rekey_t task.
+ */
+struct private_child_rekey_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ child_rekey_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Protocol of CHILD_SA to rekey
+ */
+ protocol_id_t protocol;
+
+ /**
+ * Inbound SPI of CHILD_SA to rekey
+ */
+ u_int32_t spi;
+
+ /**
+ * the CHILD_CREATE task which is reused to simplify rekeying
+ */
+ child_create_t *child_create;
+
+ /**
+ * the CHILD_DELETE task to delete rekeyed CHILD_SA
+ */
+ child_delete_t *child_delete;
+
+ /**
+ * CHILD_SA which gets rekeyed
+ */
+ child_sa_t *child_sa;
+
+ /**
+ * colliding task, may be delete or rekey
+ */
+ task_t *collision;
+};
+
+/**
+ * Implementation of task_t.build for initiator, after rekeying
+ */
+static status_t build_i_delete(private_child_rekey_t *this, message_t *message)
+{
+ /* update exchange type to INFORMATIONAL for the delete */
+ message->set_exchange_type(message, INFORMATIONAL);
+
+ return this->child_delete->task.build(&this->child_delete->task, message);
+}
+
+/**
+ * Implementation of task_t.process for initiator, after rekeying
+ */
+static status_t process_i_delete(private_child_rekey_t *this, message_t *message)
+{
+ return this->child_delete->task.process(&this->child_delete->task, message);
+}
+
+/**
+ * find a child using the REKEY_SA notify
+ */
+static void find_child(private_child_rekey_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ protocol_id_t protocol;
+ u_int32_t spi;
+
+ notify = message->get_notify(message, REKEY_SA);
+ if (notify)
+ {
+ protocol = notify->get_protocol_id(notify);
+ spi = notify->get_spi(notify);
+
+ if (protocol == PROTO_ESP || protocol == PROTO_AH)
+ {
+ this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
+ spi, FALSE);
+ }
+ }
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_child_rekey_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ u_int32_t reqid;
+ child_cfg_t *config;
+
+ this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
+ this->spi, TRUE);
+ if (!this->child_sa)
+ { /* check if it is an outbound CHILD_SA */
+ this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
+ this->spi, FALSE);
+ if (!this->child_sa)
+ { /* CHILD_SA is gone, unable to rekey. As an empty CREATE_CHILD_SA
+ * exchange is invalid, we fall back to an INFORMATIONAL exchange.*/
+ message->set_exchange_type(message, INFORMATIONAL);
+ return SUCCESS;
+ }
+ /* we work only with the inbound SPI */
+ this->spi = this->child_sa->get_spi(this->child_sa, TRUE);
+ }
+ config = this->child_sa->get_config(this->child_sa);
+
+ /* we just need the rekey notify ... */
+ notify = notify_payload_create_from_protocol_and_type(this->protocol,
+ REKEY_SA);
+ notify->set_spi(notify, this->spi);
+ message->add_payload(message, (payload_t*)notify);
+
+ /* ... our CHILD_CREATE task does the hard work for us. */
+ if (!this->child_create)
+ {
+ this->child_create = child_create_create(this->ike_sa, config, TRUE,
+ NULL, NULL);
+ }
+ reqid = this->child_sa->get_reqid(this->child_sa);
+ this->child_create->use_reqid(this->child_create, reqid);
+ this->child_create->task.build(&this->child_create->task, message);
+
+ this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_r(private_child_rekey_t *this, message_t *message)
+{
+ /* let the CHILD_CREATE task process the message */
+ this->child_create->task.process(&this->child_create->task, message);
+
+ find_child(this, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_child_rekey_t *this, message_t *message)
+{
+ u_int32_t reqid;
+
+ if (this->child_sa == NULL ||
+ this->child_sa->get_state(this->child_sa) == CHILD_DELETING)
+ {
+ DBG1(DBG_IKE, "unable to rekey, CHILD_SA not found");
+ message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ return SUCCESS;
+ }
+
+ /* let the CHILD_CREATE task build the response */
+ reqid = this->child_sa->get_reqid(this->child_sa);
+ this->child_create->use_reqid(this->child_create, reqid);
+ this->child_create->task.build(&this->child_create->task, message);
+
+ if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+ {
+ /* rekeying failed, reuse old child */
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ return SUCCESS;
+ }
+
+ this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
+
+ /* invoke rekey hook */
+ charon->bus->child_rekey(charon->bus, this->child_sa,
+ this->child_create->get_child(this->child_create));
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_child_rekey_t *this, message_t *message)
+{
+ protocol_id_t protocol;
+ u_int32_t spi;
+ child_sa_t *to_delete;
+
+ if (message->get_notify(message, NO_ADDITIONAL_SAS))
+ {
+ DBG1(DBG_IKE, "peer seems to not support CHILD_SA rekeying, "
+ "starting reauthentication");
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ return SUCCESS;
+ }
+
+ if (this->child_create->task.process(&this->child_create->task,
+ message) == NEED_MORE)
+ {
+ /* bad DH group while rekeying, try again */
+ this->child_create->task.migrate(&this->child_create->task, this->ike_sa);
+ return NEED_MORE;
+ }
+ if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+ {
+ /* establishing new child failed, reuse old. but not when we
+ * recieved a delete in the meantime */
+ if (!(this->collision &&
+ this->collision->get_type(this->collision) == CHILD_DELETE))
+ {
+ job_t *job;
+ u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+
+ job = (job_t*)rekey_child_sa_job_create(
+ this->child_sa->get_reqid(this->child_sa),
+ this->child_sa->get_protocol(this->child_sa),
+ this->child_sa->get_spi(this->child_sa, TRUE));
+ DBG1(DBG_IKE, "CHILD_SA rekeying failed, "
+ "trying again in %d seconds", retry);
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ charon->scheduler->schedule_job(charon->scheduler, job, retry);
+ }
+ return SUCCESS;
+ }
+
+ to_delete = this->child_sa;
+
+ /* check for rekey collisions */
+ if (this->collision &&
+ this->collision->get_type(this->collision) == CHILD_REKEY)
+ {
+ chunk_t this_nonce, other_nonce;
+ private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
+
+ this_nonce = this->child_create->get_lower_nonce(this->child_create);
+ other_nonce = other->child_create->get_lower_nonce(other->child_create);
+
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ if (to_delete == NULL)
+ {
+ /* ooops, should not happen, fallback */
+ to_delete = this->child_sa;
+ }
+ }
+ }
+
+ if (to_delete != this->child_create->get_child(this->child_create))
+ { /* invoke rekey hook if rekeying successful */
+ charon->bus->child_rekey(charon->bus, this->child_sa,
+ this->child_create->get_child(this->child_create));
+ }
+
+ spi = to_delete->get_spi(to_delete, TRUE);
+ protocol = to_delete->get_protocol(to_delete);
+
+ /* rekeying done, delete the obsolete CHILD_SA using a subtask */
+ this->child_delete = child_delete_create(this->ike_sa, protocol, spi);
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete;
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_child_rekey_t *this)
+{
+ return CHILD_REKEY;
+}
+
+/**
+ * Implementation of child_rekey_t.collide
+ */
+static void collide(private_child_rekey_t *this, task_t *other)
+{
+ /* the task manager only detects exchange collision, but not if
+ * the collision is for the same child. we check it here. */
+ if (other->get_type(other) == CHILD_REKEY)
+ {
+ private_child_rekey_t *rekey = (private_child_rekey_t*)other;
+ if (rekey == NULL || rekey->child_sa != this->child_sa)
+ {
+ /* not the same child => no collision */
+ other->destroy(other);
+ return;
+ }
+ }
+ else if (other->get_type(other) == CHILD_DELETE)
+ {
+ child_delete_t *del = (child_delete_t*)other;
+ if (del == NULL || del->get_child(del) != this->child_sa)
+ {
+ /* not the same child => no collision */
+ other->destroy(other);
+ return;
+ }
+ }
+ else
+ {
+ /* any other task is not critical for collisisions, ignore */
+ other->destroy(other);
+ return;
+ }
+ DESTROY_IF(this->collision);
+ this->collision = other;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa)
+{
+ if (this->child_create)
+ {
+ this->child_create->task.migrate(&this->child_create->task, ike_sa);
+ }
+ if (this->child_delete)
+ {
+ this->child_delete->task.migrate(&this->child_delete->task, ike_sa);
+ }
+ DESTROY_IF(this->collision);
+
+ this->ike_sa = ike_sa;
+ this->collision = NULL;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_child_rekey_t *this)
+{
+ if (this->child_create)
+ {
+ this->child_create->task.destroy(&this->child_create->task);
+ }
+ if (this->child_delete)
+ {
+ this->child_delete->task.destroy(&this->child_delete->task);
+ }
+ DESTROY_IF(this->collision);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi)
+{
+ private_child_rekey_t *this = malloc_thing(private_child_rekey_t);
+
+ this->public.collide = (void (*)(child_rekey_t*,task_t*))collide;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+ if (protocol != PROTO_NONE)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->initiator = TRUE;
+ this->child_create = NULL;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->initiator = FALSE;
+ this->child_create = child_create_create(ike_sa, NULL, TRUE, NULL, NULL);
+ }
+
+ this->ike_sa = ike_sa;
+ this->child_sa = NULL;
+ this->protocol = protocol;
+ this->spi = spi;
+ this->collision = NULL;
+ this->child_delete = NULL;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/child_rekey.h b/src/libcharon/sa/tasks/child_rekey.h
new file mode 100644
index 000000000..9b1aea5fa
--- /dev/null
+++ b/src/libcharon/sa/tasks/child_rekey.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup child_rekey child_rekey
+ * @{ @ingroup tasks
+ */
+
+#ifndef CHILD_REKEY_H_
+#define CHILD_REKEY_H_
+
+typedef struct child_rekey_t child_rekey_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/child_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type CHILD_REKEY, rekey an established CHILD_SA.
+ */
+struct child_rekey_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Register a rekeying task which collides with this one
+ *
+ * If two peers initiate rekeying at the same time, the collision must
+ * be handled gracefully. The task manager is aware of what exchanges
+ * are going on and notifies the outgoing task by passing the incoming.
+ *
+ * @param other incoming task
+ */
+ void (*collide)(child_rekey_t* this, task_t *other);
+};
+
+/**
+ * Create a new CHILD_REKEY task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param protocol protocol of CHILD_SA to rekey, PROTO_NONE as responder
+ * @param spi inbound SPI of CHILD_SA to rekey
+ * @return child_rekey task to handle by the task_manager
+ */
+child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi);
+
+#endif /** CHILD_REKEY_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
new file mode 100644
index 000000000..a07f96767
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details
+ */
+
+#include "ike_auth.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <sa/authenticators/eap_authenticator.h>
+
+typedef struct private_ike_auth_t private_ike_auth_t;
+
+/**
+ * Private members of a ike_auth_t task.
+ */
+struct private_ike_auth_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_auth_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Nonce chosen by us in ike_init
+ */
+ chunk_t my_nonce;
+
+ /**
+ * Nonce chosen by peer in ike_init
+ */
+ chunk_t other_nonce;
+
+ /**
+ * IKE_SA_INIT message sent by us
+ */
+ packet_t *my_packet;
+
+ /**
+ * IKE_SA_INIT message sent by peer
+ */
+ packet_t *other_packet;
+
+ /**
+ * currently active authenticator, to authenticate us
+ */
+ authenticator_t *my_auth;
+
+ /**
+ * currently active authenticator, to authenticate peer
+ */
+ authenticator_t *other_auth;
+
+ /**
+ * peer_cfg candidates, ordered by priority
+ */
+ linked_list_t *candidates;
+
+ /**
+ * selected peer config (might change when using multiple authentications)
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * have we planned an(other) authentication exchange?
+ */
+ bool do_another_auth;
+
+ /**
+ * has the peer announced another authentication exchange?
+ */
+ bool expect_another_auth;
+
+ /**
+ * should we send a AUTHENTICATION_FAILED notify?
+ */
+ bool authentication_failed;
+};
+
+/**
+ * check if multiple authentication extension is enabled, configuration-wise
+ */
+static bool multiple_auth_enabled()
+{
+ return lib->settings->get_bool(lib->settings,
+ "charon.multiple_authentication", TRUE);
+}
+
+/**
+ * collect the needed information in the IKE_SA_INIT exchange from our message
+ */
+static status_t collect_my_init_data(private_ike_auth_t *this,
+ message_t *message)
+{
+ nonce_payload_t *nonce;
+
+ /* get the nonce that was generated in ike_init */
+ nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+ if (nonce == NULL)
+ {
+ return FAILED;
+ }
+ this->my_nonce = nonce->get_nonce(nonce);
+
+ /* pre-generate the message, keep a copy */
+ if (this->ike_sa->generate_message(this->ike_sa, message,
+ &this->my_packet) != SUCCESS)
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * collect the needed information in the IKE_SA_INIT exchange from others message
+ */
+static status_t collect_other_init_data(private_ike_auth_t *this,
+ message_t *message)
+{
+ /* we collect the needed information in the IKE_SA_INIT exchange */
+ nonce_payload_t *nonce;
+
+ /* get the nonce that was generated in ike_init */
+ nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+ if (nonce == NULL)
+ {
+ return FAILED;
+ }
+ this->other_nonce = nonce->get_nonce(nonce);
+
+ /* keep a copy of the received packet */
+ this->other_packet = message->get_packet(message);
+ return NEED_MORE;
+}
+
+/**
+ * Get the next authentication configuration
+ */
+static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
+{
+ enumerator_t *e1, *e2;
+ auth_cfg_t *c1, *c2, *next = NULL;
+
+ /* find an available config not already done */
+ e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local);
+ while (e1->enumerate(e1, &c1))
+ {
+ bool found = FALSE;
+
+ e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local);
+ while (e2->enumerate(e2, &c2))
+ {
+ if (c2->complies(c2, c1, FALSE))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (!found)
+ {
+ next = c1;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return next;
+}
+
+/**
+ * Check if we have should initiate another authentication round
+ */
+static bool do_another_auth(private_ike_auth_t *this)
+{
+ bool do_another = FALSE;
+ enumerator_t *done, *todo;
+ auth_cfg_t *done_cfg, *todo_cfg;
+
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
+ {
+ return FALSE;
+ }
+
+ done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, TRUE);
+ todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE);
+ while (todo->enumerate(todo, &todo_cfg))
+ {
+ if (!done->enumerate(done, &done_cfg))
+ {
+ done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ }
+ if (!done_cfg->complies(done_cfg, todo_cfg, FALSE))
+ {
+ do_another = TRUE;
+ break;
+ }
+ }
+ done->destroy(done);
+ todo->destroy(todo);
+ return do_another;
+}
+
+/**
+ * Get peer configuration candidates from backends
+ */
+static bool load_cfg_candidates(private_ike_auth_t *this)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ host_t *me, *other;
+ identification_t *my_id, *other_id;
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ me, other, my_id, other_id);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ peer_cfg->get_ref(peer_cfg);
+ if (this->peer_cfg == NULL)
+ { /* best match */
+ this->peer_cfg = peer_cfg;
+ this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
+ }
+ else
+ {
+ this->candidates->insert_last(this->candidates, peer_cfg);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (this->peer_cfg)
+ {
+ DBG1(DBG_CFG, "selected peer config '%s'",
+ this->peer_cfg->get_name(this->peer_cfg));
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "no matching peer config found");
+ return FALSE;
+}
+
+/**
+ * update the current peer candidate if necessary, using candidates
+ */
+static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
+{
+ do
+ {
+ if (this->peer_cfg)
+ {
+ bool complies = TRUE;
+ enumerator_t *e1, *e2, *tmp;
+ auth_cfg_t *c1, *c2;
+
+ e1 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
+ e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
+
+ if (strict)
+ { /* swap lists in strict mode: all configured rounds must be
+ * fulfilled. If !strict, we check only the rounds done so far. */
+ tmp = e1;
+ e1 = e2;
+ e2 = tmp;
+ }
+ while (e1->enumerate(e1, &c1))
+ {
+ /* check if done authentications comply to configured ones */
+ if ((!e2->enumerate(e2, &c2)) ||
+ (!strict && !c1->complies(c1, c2, TRUE)) ||
+ (strict && !c2->complies(c2, c1, TRUE)))
+ {
+ complies = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+ if (complies)
+ {
+ break;
+ }
+ DBG1(DBG_CFG, "selected peer config '%s' inacceptable",
+ this->peer_cfg->get_name(this->peer_cfg));
+ this->peer_cfg->destroy(this->peer_cfg);
+ }
+ if (this->candidates->remove_first(this->candidates,
+ (void**)&this->peer_cfg) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "no alternative config found");
+ this->peer_cfg = NULL;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "switching to peer config '%s'",
+ this->peer_cfg->get_name(this->peer_cfg));
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+ }
+ }
+ while (this->peer_cfg);
+
+ return this->peer_cfg != NULL;
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_ike_auth_t *this, message_t *message)
+{
+ auth_cfg_t *cfg;
+
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return collect_my_init_data(this, message);
+ }
+
+ if (this->peer_cfg == NULL)
+ {
+ this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->peer_cfg->get_ref(this->peer_cfg);
+ }
+
+ if (message->get_message_id(message) == 1)
+ { /* in the first IKE_AUTH ... */
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
+ { /* indicate support for multiple authentication */
+ message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
+ chunk_empty);
+ }
+ /* indicate support for EAP-only authentication */
+ message->add_notify(message, FALSE, EAP_ONLY_AUTHENTICATION,
+ chunk_empty);
+ }
+
+ if (!this->do_another_auth && !this->my_auth)
+ { /* we have done our rounds */
+ return NEED_MORE;
+ }
+
+ /* check if an authenticator is in progress */
+ if (this->my_auth == NULL)
+ {
+ identification_t *id;
+ id_payload_t *id_payload;
+
+ /* clean up authentication config from a previous round */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->purge(cfg, TRUE);
+
+ /* add (optional) IDr */
+ cfg = get_auth_cfg(this, FALSE);
+ if (cfg)
+ {
+ id = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (id && !id->contains_wildcards(id))
+ {
+ this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(
+ ID_RESPONDER, id);
+ message->add_payload(message, (payload_t*)id_payload);
+ }
+ }
+ /* add IDi */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
+ id = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "configuration misses IDi");
+ return FAILED;
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ /* build authentication data */
+ this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
+ this->other_nonce, this->my_nonce,
+ this->other_packet->get_data(this->other_packet),
+ this->my_packet->get_data(this->my_packet));
+ if (!this->my_auth)
+ {
+ return FAILED;
+ }
+ }
+ switch (this->my_auth->build(this->my_auth, message))
+ {
+ case SUCCESS:
+ /* authentication step complete, reset authenticator */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ return FAILED;
+ }
+
+ /* check for additional authentication rounds */
+ if (do_another_auth(this))
+ {
+ if (message->get_payload(message, AUTHENTICATION))
+ {
+ message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
+ }
+ }
+ else
+ {
+ this->do_another_auth = FALSE;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_auth_t *this, message_t *message)
+{
+ auth_cfg_t *cfg, *cand;
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return collect_other_init_data(this, message);
+ }
+
+ 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);
+ if (id_payload)
+ {
+ id = id_payload->get_identification(id_payload);
+ }
+ else
+ {
+ id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id);
+ }
+
+ if (!this->expect_another_auth)
+ {
+ return NEED_MORE;
+ }
+
+ if (message->get_message_id(message) == 1)
+ { /* check for extensions in the first IKE_AUTH */
+ if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
+ }
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
+ message->get_notify(message, EAP_ONLY_AUTHENTICATION))
+ { /* EAP-only has no official notify, accept only from strongSwan */
+ this->ike_sa->enable_extension(this->ike_sa,
+ EXT_EAP_ONLY_AUTHENTICATION);
+ }
+ }
+
+ if (this->other_auth == NULL)
+ {
+ /* handle IDi payload */
+ id_payload = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDi payload missing");
+ return FAILED;
+ }
+ id = id_payload->get_identification(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
+
+ if (this->peer_cfg == NULL)
+ {
+ if (!load_cfg_candidates(this))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ }
+ if (message->get_payload(message, AUTHENTICATION) == NULL)
+ { /* before authenticating with EAP, we need a EAP config */
+ cand = get_auth_cfg(this, FALSE);
+ while (!cand || (
+ (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
+ (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
+ { /* peer requested EAP, but current config does not match */
+ this->peer_cfg->destroy(this->peer_cfg);
+ this->peer_cfg = NULL;
+ if (!update_cfg_candidates(this, FALSE))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ cand = get_auth_cfg(this, FALSE);
+ }
+ cfg->merge(cfg, cand, TRUE);
+ }
+
+ /* verify authentication data */
+ this->other_auth = authenticator_create_verifier(this->ike_sa,
+ message, this->other_nonce, this->my_nonce,
+ this->other_packet->get_data(this->other_packet),
+ this->my_packet->get_data(this->my_packet));
+ if (!this->other_auth)
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ }
+ switch (this->other_auth->process(this->other_auth, message))
+ {
+ case SUCCESS:
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
+ break;
+ case NEED_MORE:
+ if (message->get_payload(message, AUTHENTICATION))
+ { /* AUTH verification successful, but another build() needed */
+ break;
+ }
+ return NEED_MORE;
+ default:
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+
+ /* store authentication information */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
+
+ /* another auth round done, invoke authorize hook */
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "authorization hook forbids IKE_SA, cancelling");
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+
+ if (!update_cfg_candidates(this, FALSE))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+
+ if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
+ {
+ this->expect_another_auth = FALSE;
+ if (!update_cfg_candidates(this, TRUE))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_auth_t *this, message_t *message)
+{
+ auth_cfg_t *cfg;
+
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ if (multiple_auth_enabled())
+ {
+ message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
+ chunk_empty);
+ }
+ return collect_my_init_data(this, message);
+ }
+
+ if (this->authentication_failed || this->peer_cfg == NULL)
+ {
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
+ return FAILED;
+ }
+
+ if (this->my_auth == NULL && this->do_another_auth)
+ {
+ identification_t *id, *id_cfg;
+ id_payload_t *id_payload;
+
+ /* add IDr */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->purge(cfg, TRUE);
+ cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
+
+ id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ if (id->get_type(id) == ID_ANY)
+ { /* no IDr received, apply configured ID */
+ if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
+ {
+ DBG1(DBG_CFG, "IDr not configured and negotiation failed");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
+ id = id_cfg;
+ }
+ else
+ { /* IDr received, check if it matches configuration */
+ if (id_cfg && !id->matches(id, id_cfg))
+ {
+ DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg);
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ }
+
+ id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
+ { /* EAP-only authentication */
+ if (!this->ike_sa->supports_extension(this->ike_sa,
+ EXT_EAP_ONLY_AUTHENTICATION))
+ {
+ DBG1(DBG_IKE, "configured EAP-only authentication, but peer "
+ "does not support it");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ }
+ else
+ {
+ /* build authentication data */
+ this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
+ this->other_nonce, this->my_nonce,
+ this->other_packet->get_data(this->other_packet),
+ this->my_packet->get_data(this->my_packet));
+ if (!this->my_auth)
+ {
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ }
+ }
+
+ if (this->other_auth)
+ {
+ switch (this->other_auth->build(this->other_auth, message))
+ {
+ case SUCCESS:
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ if (!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+ { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ }
+ return FAILED;
+ }
+ }
+ if (this->my_auth)
+ {
+ switch (this->my_auth->build(this->my_auth, message))
+ {
+ case SUCCESS:
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
+ TRUE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ }
+
+ /* check for additional authentication rounds */
+ if (do_another_auth(this))
+ {
+ message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
+ }
+ else
+ {
+ this->do_another_auth = FALSE;
+ }
+ if (!this->do_another_auth && !this->expect_another_auth)
+ {
+ if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+ this->ike_sa))
+ {
+ DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ if (!charon->bus->authorize(charon->bus, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_auth_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ auth_cfg_t *cfg;
+ bool mutual_eap = FALSE;
+
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
+ multiple_auth_enabled())
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
+ }
+ return collect_other_init_data(this, message);
+ }
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ case NO_PROPOSAL_CHOSEN:
+ case SINGLE_PAIR_REQUIRED:
+ case NO_ADDITIONAL_SAS:
+ case INTERNAL_ADDRESS_FAILURE:
+ case FAILED_CP_REQUIRED:
+ case TS_UNACCEPTABLE:
+ case INVALID_SELECTORS:
+ /* these are errors, but are not critical as only the
+ * CHILD_SA won't get build, but IKE_SA establishes anyway */
+ break;
+ case MOBIKE_SUPPORTED:
+ case ADDITIONAL_IP4_ADDRESS:
+ case ADDITIONAL_IP6_ADDRESS:
+ /* handled in ike_mobike task */
+ break;
+ case AUTH_LIFETIME:
+ /* handled in ike_auth_lifetime task */
+ break;
+ case ME_ENDPOINT:
+ /* handled in ike_me task */
+ break;
+ default:
+ {
+ if (type < 16383)
+ {
+ DBG1(DBG_IKE, "received %N notify error",
+ notify_type_names, type);
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ DBG2(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ break;
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->expect_another_auth)
+ {
+ if (this->other_auth == NULL)
+ {
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ /* handle IDr payload */
+ id_payload = (id_payload_t*)message->get_payload(message,
+ ID_RESPONDER);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDr payload missing");
+ return FAILED;
+ }
+ id = id_payload->get_identification(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+ 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))
+ {
+ /* verify authentication data */
+ this->other_auth = authenticator_create_verifier(this->ike_sa,
+ message, this->other_nonce, this->my_nonce,
+ this->other_packet->get_data(this->other_packet),
+ this->my_packet->get_data(this->my_packet));
+ if (!this->other_auth)
+ {
+ return FAILED;
+ }
+ }
+ else
+ {
+ /* responder omitted AUTH payload, indicating EAP-only */
+ mutual_eap = TRUE;
+ }
+ }
+ if (this->other_auth)
+ {
+ switch (this->other_auth->process(this->other_auth, message))
+ {
+ case SUCCESS:
+ break;
+ case NEED_MORE:
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
+ }
+ /* store authentication information, reset authenticator */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
+
+ /* another auth round done, invoke authorize hook */
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling");
+ return FAILED;
+ }
+ }
+
+ if (this->my_auth)
+ {
+ switch (this->my_auth->process(this->my_auth, message))
+ {
+ case SUCCESS:
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
+ TRUE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ this->do_another_auth = do_another_auth(this);
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ if (mutual_eap)
+ {
+ if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth))
+ {
+ DBG1(DBG_IKE, "do not allow non-mutual EAP-only authentication");
+ return FAILED;
+ }
+ DBG1(DBG_IKE, "allow mutual EAP-only authentication");
+ }
+
+ if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
+ {
+ this->expect_another_auth = FALSE;
+ }
+ if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
+ {
+ if (!update_cfg_candidates(this, TRUE))
+ {
+ return FAILED;
+ }
+ if (!charon->bus->authorize(charon->bus, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ return FAILED;
+ }
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_auth_t *this)
+{
+ return IKE_AUTHENTICATE;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
+{
+ chunk_free(&this->my_nonce);
+ chunk_free(&this->other_nonce);
+ DESTROY_IF(this->my_packet);
+ DESTROY_IF(this->other_packet);
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->my_auth);
+ DESTROY_IF(this->other_auth);
+ this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
+
+ this->my_packet = NULL;
+ this->other_packet = NULL;
+ this->ike_sa = ike_sa;
+ this->peer_cfg = NULL;
+ this->my_auth = NULL;
+ this->other_auth = NULL;
+ this->do_another_auth = TRUE;
+ this->expect_another_auth = TRUE;
+ this->authentication_failed = FALSE;
+ this->candidates = linked_list_create();
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_auth_t *this)
+{
+ chunk_free(&this->my_nonce);
+ chunk_free(&this->other_nonce);
+ DESTROY_IF(this->my_packet);
+ DESTROY_IF(this->other_packet);
+ DESTROY_IF(this->my_auth);
+ DESTROY_IF(this->other_auth);
+ DESTROY_IF(this->peer_cfg);
+ this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->my_nonce = chunk_empty;
+ this->other_nonce = chunk_empty;
+ this->my_packet = NULL;
+ this->other_packet = NULL;
+ this->peer_cfg = NULL;
+ this->candidates = linked_list_create();
+ this->my_auth = NULL;
+ this->other_auth = NULL;
+ this->do_another_auth = TRUE;
+ this->expect_another_auth = TRUE;
+ this->authentication_failed = FALSE;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_auth.h b/src/libcharon/sa/tasks/ike_auth.h
new file mode 100644
index 000000000..bba46d961
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_auth.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_auth ike_auth
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_AUTH_H_
+#define IKE_AUTH_H_
+
+typedef struct ike_auth_t ike_auth_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_auth, authenticates an IKE_SA using authenticators.
+ *
+ * The ike_auth task authenticates the IKE_SA using the IKE_AUTH
+ * exchange. It processes and build IDi and IDr payloads and also
+ * handles AUTH payloads. The AUTH payloads are passed to authenticator_t's,
+ * which do the actual authentication process. If the ike_auth task is used
+ * with EAP authentication, it stays alive over multiple exchanges until
+ * EAP has completed.
+ */
+struct ike_auth_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new task of type IKE_AUTHENTICATE.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the initator of an exchange
+ * @return ike_auth task to handle by the task_manager
+ */
+ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_AUTH_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_auth_lifetime.c b/src/libcharon/sa/tasks/ike_auth_lifetime.c
new file mode 100644
index 000000000..75ff35168
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_auth_lifetime.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_auth_lifetime.h"
+
+#include <time.h>
+
+#include <daemon.h>
+#include <encoding/payloads/notify_payload.h>
+
+
+typedef struct private_ike_auth_lifetime_t private_ike_auth_lifetime_t;
+
+/**
+ * Private members of a ike_auth_lifetime_t task.
+ */
+struct private_ike_auth_lifetime_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_auth_lifetime_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+};
+
+/**
+ * add the AUTH_LIFETIME notify to the message
+ */
+static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ chunk_t chunk;
+ u_int32_t lifetime;
+
+ lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH);
+ if (lifetime)
+ {
+ lifetime -= time_monotonic(NULL);
+ chunk = chunk_from_thing(lifetime);
+ *(u_int32_t*)chunk.ptr = htonl(lifetime);
+ message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
+ }
+}
+
+/**
+ * read notifys from message and evaluate them
+ */
+static void process_payloads(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ chunk_t data;
+ u_int32_t lifetime;
+
+ notify = message->get_notify(message, AUTH_LIFETIME);
+ if (notify)
+ {
+ data = notify->get_notification_data(notify);
+ lifetime = ntohl(*(u_int32_t*)data.ptr);
+ this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime);
+ }
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ add_auth_lifetime(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ process_payloads(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ {
+ add_auth_lifetime(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_auth_lifetime_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ {
+ process_payloads(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_auth_lifetime_t *this)
+{
+ return IKE_AUTH_LIFETIME;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_auth_lifetime_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_auth_lifetime_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_auth_lifetime_t *this = malloc_thing(private_ike_auth_lifetime_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_auth_lifetime.h b/src/libcharon/sa/tasks/ike_auth_lifetime.h
new file mode 100644
index 000000000..3b129b9e3
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_auth_lifetime.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_auth_lifetime ike_auth_lifetime
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_AUTH_LIFETIME_H_
+#define IKE_AUTH_LIFETIME_H_
+
+typedef struct ike_auth_lifetime_t ike_auth_lifetime_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type IKE_AUTH_LIFETIME, implements RFC4478.
+ *
+ * This task exchanges lifetimes for IKE_AUTH to force a client to
+ * reauthenticate before the responders lifetime reaches the limit.
+ */
+struct ike_auth_lifetime_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new IKE_AUTH_LIFETIME task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if taks is initiated by us
+ * @return ike_auth_lifetime task to handle by the task_manager
+ */
+ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_MOBIKE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c
new file mode 100644
index 000000000..c831df975
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_cert_post.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2006-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 "ike_cert_post.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_ike_cert_post_t private_ike_cert_post_t;
+
+/**
+ * Private members of a ike_cert_post_t task.
+ */
+struct private_ike_cert_post_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_cert_post_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+};
+
+/**
+ * Generates the cert payload, if possible with "Hash and URL"
+ */
+static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
+ certificate_t *cert)
+{
+ hasher_t *hasher;
+ identification_t *id;
+ chunk_t hash, encoded ;
+ enumerator_t *enumerator;
+ char *url;
+ cert_payload_t *payload = NULL;
+
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
+ {
+ return cert_payload_create_from_cert(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(cert);
+ }
+
+ encoded = cert->get_encoding(cert);
+ hasher->allocate_hash(hasher, encoded, &hash);
+ chunk_free(&encoded);
+ hasher->destroy(hasher);
+ id = identification_create_from_encoding(ID_KEY_ID, hash);
+
+ enumerator = charon->credentials->create_cdp_enumerator(charon->credentials,
+ CERT_X509, id);
+ if (enumerator->enumerate(enumerator, &url))
+ {
+ payload = cert_payload_create_from_hash_and_url(hash, url);
+ }
+ else
+ {
+ payload = cert_payload_create_from_cert(cert);
+ }
+ enumerator->destroy(enumerator);
+ chunk_free(&hash);
+ id->destroy(id);
+ return payload;
+}
+
+/**
+ * add certificates to message
+ */
+static void build_certs(private_ike_cert_post_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+ auth_payload_t *payload;
+
+ payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ 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 */
+ return;
+ }
+
+ switch (peer_cfg->get_cert_policy(peer_cfg))
+ {
+ case CERT_NEVER_SEND:
+ break;
+ case CERT_SEND_IF_ASKED:
+ if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
+ {
+ break;
+ }
+ /* FALL */
+ case CERT_ALWAYS_SEND:
+ {
+ cert_payload_t *payload;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ auth_rule_t type;
+ auth_cfg_t *auth;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+
+ /* get subject cert first, then issuing certificates */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!cert)
+ {
+ break;
+ }
+ payload = build_cert_payload(this, cert);
+ if (!payload)
+ {
+ break;
+ }
+ DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &cert))
+ {
+ if (type == AUTH_RULE_IM_CERT)
+ {
+ payload = cert_payload_create_from_cert(cert);
+ if (payload)
+ {
+ DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_cert_post_t *this, message_t *message)
+{
+ build_certs(this, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_cert_post_t *this, message_t *message)
+{
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_cert_post_t *this, message_t *message)
+{
+ build_certs(this, message);
+
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* stay alive, we might have additional rounds with certs */
+ return NEED_MORE;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_cert_post_t *this, message_t *message)
+{
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* stay alive, we might have additional rounds with CERTS */
+ return NEED_MORE;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_cert_post_t *this)
+{
+ return IKE_CERT_POST;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_cert_post_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_cert_post.h b/src/libcharon/sa/tasks/ike_cert_post.h
new file mode 100644
index 000000000..a21f45927
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_cert_post.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007-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 ike_cert_post ike_cert_post
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_CERT_POST_H_
+#define IKE_CERT_POST_H_
+
+typedef struct ike_cert_post_t ike_cert_post_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_cert_post, certificate processing after authentication.
+ */
+struct ike_cert_post_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_cert_post task.
+ *
+ * The initiator parameter means the original initiator, not the initiator
+ * of the certificate request.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the original initator
+ * @return ike_cert_post task to handle by the task_manager
+ */
+ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_CERT_POST_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
new file mode 100644
index 000000000..0805d0290
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2006-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 "ike_cert_pre.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_ike_cert_pre_t private_ike_cert_pre_t;
+
+/**
+ * Private members of a ike_cert_pre_t task.
+ */
+struct private_ike_cert_pre_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_cert_pre_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Do we accept HTTP certificate lookup requests
+ */
+ bool do_http_lookup;
+
+ /**
+ * wheter this is the final authentication round
+ */
+ bool final;
+};
+
+/**
+ * read certificate requests
+ */
+static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ auth_cfg_t *auth;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case CERTIFICATE_REQUEST:
+ {
+ certreq_payload_t *certreq = (certreq_payload_t*)payload;
+ enumerator_t *enumerator;
+ chunk_t keyid;
+
+ this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
+
+ if (certreq->get_cert_type(certreq) != CERT_X509)
+ {
+ DBG1(DBG_IKE, "cert payload %N not supported - ignored",
+ certificate_type_names, certreq->get_cert_type(certreq));
+ break;
+ }
+ enumerator = certreq->create_keyid_enumerator(certreq);
+ while (enumerator->enumerate(enumerator, &keyid))
+ {
+ identification_t *id;
+ certificate_t *cert;
+
+ id = identification_create_from_encoding(ID_KEY_ID, keyid);
+ cert = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, id, TRUE);
+ if (cert)
+ {
+ DBG1(DBG_IKE, "received cert request for \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_RULE_CA_CERT, cert);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received cert request for unknown ca "
+ "with keyid %Y", id);
+ }
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+ break;
+ }
+ case NOTIFY:
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ /* we only handle one type of notify here */
+ if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED)
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL);
+ }
+ break;
+ }
+ default:
+ /* ignore other payloads here, these are handled elsewhere */
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * tries to extract a certificate from the cert payload or the credential
+ * manager (based on the hash of a "Hash and URL" encoded cert).
+ * Note: the returned certificate (if any) has to be destroyed
+ */
+static certificate_t *try_get_cert(cert_payload_t *cert_payload)
+{
+ certificate_t *cert = NULL;
+
+ switch (cert_payload->get_cert_encoding(cert_payload))
+ {
+ case ENC_X509_SIGNATURE:
+ {
+ cert = cert_payload->get_cert(cert_payload);
+ break;
+ }
+ case ENC_X509_HASH_AND_URL:
+ {
+ identification_t *id;
+ chunk_t hash = cert_payload->get_hash(cert_payload);
+ if (!hash.ptr)
+ {
+ /* invalid "Hash and URL" data (logged elsewhere) */
+ break;
+ }
+ id = identification_create_from_encoding(ID_KEY_ID, hash);
+ cert = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, id, FALSE);
+ id->destroy(id);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return cert;
+}
+
+/**
+ * import certificates
+ */
+static void process_certs(private_ike_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ auth_cfg_t *auth;
+ bool first = TRUE;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == CERTIFICATE)
+ {
+ cert_payload_t *cert_payload;
+ cert_encoding_t encoding;
+ certificate_t *cert;
+ char *url;
+
+ cert_payload = (cert_payload_t*)payload;
+ encoding = cert_payload->get_cert_encoding(cert_payload);
+
+ switch (encoding)
+ {
+ case ENC_X509_HASH_AND_URL:
+ {
+ if (!this->do_http_lookup)
+ {
+ DBG1(DBG_IKE, "received hash-and-url encoded cert, but"
+ " we don't accept them, ignore");
+ break;
+ }
+ /* FALL */
+ }
+ case ENC_X509_SIGNATURE:
+ {
+ cert = try_get_cert(cert_payload);
+ if (cert)
+ {
+ if (first)
+ { /* the first is an end entity certificate */
+ DBG1(DBG_IKE, "received end entity cert \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
+ first = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received issuer cert \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_HELPER_IM_CERT, cert);
+ }
+ }
+ else if (encoding == ENC_X509_HASH_AND_URL)
+ {
+ /* we fetch the certificate not yet, but only if
+ * it is really needed during authentication */
+ url = cert_payload->get_url(cert_payload);
+ if (!url)
+ {
+ DBG1(DBG_IKE, "received invalid hash-and-url "
+ "encoded cert, ignore");
+ break;
+ }
+ url = strdup(url);
+ if (first)
+ { /* first URL is for an end entity certificate */
+ DBG1(DBG_IKE, "received hash-and-url for end"
+ " entity cert \"%s\"", url);
+ auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url);
+ first = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received hash-and-url for issuer"
+ " cert \"%s\"", url);
+ auth->add(auth, AUTH_HELPER_IM_HASH_URL, url);
+ }
+ }
+ break;
+ }
+ case ENC_PKCS7_WRAPPED_X509:
+ case ENC_PGP:
+ case ENC_DNS_SIGNED_KEY:
+ case ENC_KERBEROS_TOKEN:
+ case ENC_CRL:
+ case ENC_ARL:
+ case ENC_SPKI:
+ case ENC_X509_ATTRIBUTE:
+ case ENC_RAW_RSA_KEY:
+ case ENC_X509_HASH_AND_URL_BUNDLE:
+ case ENC_OCSP_CONTENT:
+ default:
+ DBG1(DBG_ENC, "certificate encoding %N not supported",
+ cert_encoding_names, encoding);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * add the keyid of a certificate to the certificate request payload
+ */
+static void add_certreq(certreq_payload_t **req, certificate_t *cert)
+{
+ switch (cert->get_type(cert))
+ {
+ case CERT_X509:
+ {
+ public_key_t *public;
+ chunk_t keyid;
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ { /* no CA cert, skip */
+ break;
+ }
+ public = cert->get_public_key(cert);
+ if (!public)
+ {
+ break;
+ }
+ if (*req == NULL)
+ {
+ *req = certreq_payload_create_type(CERT_X509);
+ }
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ {
+ (*req)->add_keyid(*req, keyid);
+ DBG1(DBG_IKE, "sending cert request for \"%Y\"",
+ cert->get_subject(cert));
+ }
+ public->destroy(public);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * add a auth_cfg's CA certificates to the certificate request
+ */
+static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ add_certreq(req, (certificate_t*)value);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * build certificate requests
+ */
+static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
+ certificate_t *cert;
+ auth_cfg_t *auth;
+ certreq_payload_t *req = NULL;
+
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (!ike_cfg->send_certreq(ike_cfg))
+ {
+ return;
+ }
+
+ /* check if we require a specific CA for that peer */
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ add_certreqs(&req, auth);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (!req)
+ {
+ /* otherwise add all trusted CA certificates */
+ enumerator = charon->credentials->create_cert_enumerator(
+ charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ add_certreq(&req, cert);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (req)
+ {
+ message->add_payload(message, (payload_t*)req);
+
+ if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE))
+ {
+ message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
+ chunk_empty);
+ this->do_http_lookup = TRUE;
+ }
+ }
+}
+
+/**
+ * Check if this is the final authentication round
+ */
+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)
+ {
+ return FALSE;
+ }
+ if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_message_id(message) == 1)
+ { /* initiator sends CERTREQs in first IKE_AUTH */
+ build_certreqs(this, message);
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) != IKE_SA_INIT)
+ { /* handle certreqs/certs in any IKE_AUTH, just in case */
+ process_certreqs(this, message);
+ process_certs(this, message);
+ }
+ this->final = final_auth(message);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ build_certreqs(this, message);
+ }
+ if (this->final)
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ process_certreqs(this, message);
+ }
+ process_certs(this, message);
+
+ if (final_auth(message))
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_cert_pre_t *this)
+{
+ return IKE_CERT_PRE;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_cert_pre_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_cert_pre_t *this = malloc_thing(private_ike_cert_pre_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->do_http_lookup = FALSE;
+ this->final = FALSE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.h b/src/libcharon/sa/tasks/ike_cert_pre.h
new file mode 100644
index 000000000..1541b80e5
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_cert_pre.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007-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 ike_cert_pre ike_cert_pre
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_CERT_PRE_H_
+#define IKE_CERT_PRE_H_
+
+typedef struct ike_cert_pre_t ike_cert_pre_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_cert_post, certificate processing before authentication.
+ */
+struct ike_cert_pre_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_cert_pre task.
+ *
+ * The initiator parameter means the original initiator, not the initiator
+ * of the certificate request.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the original initator
+ * @return ike_cert_pre task to handle by the task_manager
+ */
+ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_CERT_PRE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c
new file mode 100644
index 000000000..58bcf0762
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_config.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_config.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <encoding/payloads/cp_payload.h>
+
+typedef struct private_ike_config_t private_ike_config_t;
+
+/**
+ * Private members of a ike_config_t task.
+ */
+struct private_ike_config_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_config_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * virtual ip
+ */
+ host_t *virtual_ip;
+
+ /**
+ * list of attributes requested and its handler, entry_t
+ */
+ linked_list_t *requested;
+};
+
+/**
+ * Entry for a requested attribute and the requesting handler
+ */
+typedef struct {
+ /** attribute requested */
+ configuration_attribute_type_t type;
+ /** handler requesting this attribute */
+ attribute_handler_t *handler;
+} entry_t;
+
+/**
+ * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
+ */
+static configuration_attribute_t *build_vip(host_t *vip)
+{
+ configuration_attribute_type_t type;
+ chunk_t chunk, prefix;
+
+ if (vip->get_family(vip) == AF_INET)
+ {
+ type = INTERNAL_IP4_ADDRESS;
+ if (vip->is_anyaddr(vip))
+ {
+ chunk = chunk_empty;
+ }
+ else
+ {
+ chunk = vip->get_address(vip);
+ }
+ }
+ else
+ {
+ type = INTERNAL_IP6_ADDRESS;
+ if (vip->is_anyaddr(vip))
+ {
+ chunk = chunk_empty;
+ }
+ else
+ {
+ prefix = chunk_alloca(1);
+ *prefix.ptr = 64;
+ chunk = vip->get_address(vip);
+ chunk = chunk_cata("cc", chunk, prefix);
+ }
+ }
+ return configuration_attribute_create_value(type, chunk);
+}
+
+/**
+ * Handle a received attribute as initiator
+ */
+static void handle_attribute(private_ike_config_t *this,
+ configuration_attribute_t *ca)
+{
+ attribute_handler_t *handler = NULL;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ /* find the handler which requested this attribute */
+ enumerator = this->requested->create_enumerator(this->requested);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->type == ca->get_type(ca))
+ {
+ handler = entry->handler;
+ this->requested->remove_at(this->requested, enumerator);
+ free(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* and pass it to the handle function */
+ handler = hydra->attributes->handle(hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), handler,
+ ca->get_type(ca), ca->get_value(ca));
+ if (handler)
+ {
+ this->ike_sa->add_configuration_attribute(this->ike_sa,
+ handler, ca->get_type(ca), ca->get_value(ca));
+ }
+}
+
+/**
+ * process a single configuration attribute
+ */
+static void process_attribute(private_ike_config_t *this,
+ configuration_attribute_t *ca)
+{
+ host_t *ip;
+ chunk_t addr;
+ int family = AF_INET6;
+
+ switch (ca->get_type(ca))
+ {
+ case INTERNAL_IP4_ADDRESS:
+ family = AF_INET;
+ /* fall */
+ case INTERNAL_IP6_ADDRESS:
+ {
+ addr = ca->get_value(ca);
+ if (addr.len == 0)
+ {
+ ip = host_create_any(family);
+ }
+ else
+ {
+ /* skip prefix byte in IPv6 payload*/
+ if (family == AF_INET6)
+ {
+ addr.len--;
+ }
+ ip = host_create_from_chunk(family, addr, 0);
+ }
+ if (ip)
+ {
+ DESTROY_IF(this->virtual_ip);
+ this->virtual_ip = ip;
+ }
+ break;
+ }
+ default:
+ {
+ if (this->initiator)
+ {
+ handle_attribute(this, ca);
+ }
+ }
+ }
+}
+
+/**
+ * Scan for configuration payloads and attributes
+ */
+static void process_payloads(private_ike_config_t *this, message_t *message)
+{
+ enumerator_t *enumerator, *attributes;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == CONFIGURATION)
+ {
+ cp_payload_t *cp = (cp_payload_t*)payload;
+ configuration_attribute_t *ca;
+
+ switch (cp->get_type(cp))
+ {
+ case CFG_REQUEST:
+ case CFG_REPLY:
+ {
+ attributes = cp->create_attribute_enumerator(cp);
+ while (attributes->enumerate(attributes, &ca))
+ {
+ DBG2(DBG_IKE, "processing %N attribute",
+ configuration_attribute_type_names, ca->get_type(ca));
+ process_attribute(this, ca);
+ }
+ attributes->destroy(attributes);
+ break;
+ }
+ default:
+ DBG1(DBG_IKE, "ignoring %N config payload",
+ config_type_names, cp->get_type(cp));
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_config_t *this, message_t *message)
+{
+ if (message->get_message_id(message) == 1)
+ { /* in first IKE_AUTH only */
+ cp_payload_t *cp = NULL;
+ enumerator_t *enumerator;
+ attribute_handler_t *handler;
+ peer_cfg_t *config;
+ configuration_attribute_type_t type;
+ chunk_t data;
+ host_t *vip;
+
+ /* reuse virtual IP if we already have one */
+ vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (!vip)
+ {
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ vip = config->get_virtual_ip(config);
+ }
+ if (vip)
+ {
+ cp = cp_payload_create_type(CFG_REQUEST);
+ cp->add_attribute(cp, build_vip(vip));
+ }
+
+ enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vip);
+ while (enumerator->enumerate(enumerator, &handler, &type, &data))
+ {
+ configuration_attribute_t *ca;
+ entry_t *entry;
+
+ /* create configuration attribute */
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ ca = configuration_attribute_create_value(type, data);
+ if (!cp)
+ {
+ cp = cp_payload_create_type(CFG_REQUEST);
+ }
+ cp->add_attribute(cp, ca);
+
+ /* save handler along with requested type */
+ entry = malloc_thing(entry_t);
+ entry->type = type;
+ entry->handler = handler;
+
+ this->requested->insert_last(this->requested, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ if (cp)
+ {
+ message->add_payload(message, (payload_t*)cp);
+ }
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_config_t *this, message_t *message)
+{
+ if (message->get_message_id(message) == 1)
+ { /* in first IKE_AUTH only */
+ process_payloads(this, message);
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_config_t *this, message_t *message)
+{
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ { /* in last IKE_AUTH exchange */
+ enumerator_t *enumerator;
+ configuration_attribute_type_t type;
+ chunk_t value;
+ host_t *vip = NULL;
+ cp_payload_t *cp = NULL;
+ peer_cfg_t *config;
+ identification_t *id;
+
+ id = this->ike_sa->get_other_eap_id(this->ike_sa);
+
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (config && this->virtual_ip)
+ {
+ DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
+ if (config->get_pool(config))
+ {
+ vip = hydra->attributes->acquire_address(hydra->attributes,
+ config->get_pool(config), id, this->virtual_ip);
+ }
+ if (vip == NULL)
+ {
+ DBG1(DBG_IKE, "no virtual IP found, sending %N",
+ notify_type_names, INTERNAL_ADDRESS_FAILURE);
+ message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
+ chunk_empty);
+ return SUCCESS;
+ }
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
+ this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
+
+ cp = cp_payload_create_type(CFG_REPLY);
+ cp->add_attribute(cp, build_vip(vip));
+ }
+
+ /* query registered providers for additional attributes to include */
+ enumerator = hydra->attributes->create_responder_enumerator(
+ hydra->attributes, id, vip);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ if (!cp)
+ {
+ cp = cp_payload_create_type(CFG_REPLY);
+ }
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ cp->add_attribute(cp,
+ configuration_attribute_create_value(type, value));
+ }
+ enumerator->destroy(enumerator);
+
+ if (cp)
+ {
+ message->add_payload(message, (payload_t*)cp);
+ }
+ DESTROY_IF(vip);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_config_t *this, message_t *message)
+{
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ { /* in last IKE_AUTH exchange */
+
+ process_payloads(this, message);
+
+ if (this->virtual_ip)
+ {
+ this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
+ }
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_config_t *this)
+{
+ return IKE_CONFIG;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
+{
+ DESTROY_IF(this->virtual_ip);
+
+ this->ike_sa = ike_sa;
+ this->virtual_ip = NULL;
+ this->requested->destroy_function(this->requested, free);
+ this->requested = linked_list_create();
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_config_t *this)
+{
+ DESTROY_IF(this->virtual_ip);
+ this->requested->destroy_function(this->requested, free);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_config_t *this = malloc_thing(private_ike_config_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ this->initiator = initiator;
+ this->ike_sa = ike_sa;
+ this->virtual_ip = NULL;
+ this->requested = linked_list_create();
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_config.h b/src/libcharon/sa/tasks/ike_config.h
new file mode 100644
index 000000000..8cef08697
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_config.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_config ike_config
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_CONFIG_H_
+#define IKE_CONFIG_H_
+
+typedef struct ike_config_t ike_config_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type IKE_CONFIG, sets up a virtual IP and other
+ * configurations for an IKE_SA.
+ */
+struct ike_config_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_config task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE for initiator
+ * @return ike_config task to handle by the task_manager
+ */
+ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_CONFIG_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_delete.c b/src/libcharon/sa/tasks/ike_delete.c
new file mode 100644
index 000000000..130948836
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_delete.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2006-2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_delete.h"
+
+#include <daemon.h>
+#include <encoding/payloads/delete_payload.h>
+
+
+typedef struct private_ike_delete_t private_ike_delete_t;
+
+/**
+ * Private members of a ike_delete_t task.
+ */
+struct private_ike_delete_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_delete_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * are we deleting a rekeyed SA?
+ */
+ bool rekeyed;
+
+ /**
+ * are we responding to a delete, but have initated our own?
+ */
+ bool simultaneous;
+};
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_ike_delete_t *this, message_t *message)
+{
+ delete_payload_t *delete_payload;
+
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ delete_payload = delete_payload_create(PROTO_IKE);
+ message->add_payload(message, (payload_t*)delete_payload);
+
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
+ {
+ this->rekeyed = TRUE;
+ }
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+
+ DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_delete_t *this, message_t *message)
+{
+ DBG0(DBG_IKE, "IKE_SA deleted");
+ if (!this->rekeyed)
+ { /* invoke ike_down() hook if SA has not been rekeyed */
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ /* completed, delete IKE_SA by returning DESTROY_ME */
+ return DESTROY_ME;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_delete_t *this, message_t *message)
+{
+ /* we don't even scan the payloads, as the message wouldn't have
+ * come so far without being correct */
+ DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_ESTABLISHED:
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+ this->ike_sa->reestablish(this->ike_sa);
+ return NEED_MORE;
+ case IKE_REKEYING:
+ this->rekeyed = TRUE;
+ break;
+ case IKE_DELETING:
+ this->simultaneous = TRUE;
+ break;
+ default:
+ break;
+ }
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_delete_t *this, message_t *message)
+{
+ DBG0(DBG_IKE, "IKE_SA deleted");
+
+ if (this->simultaneous)
+ {
+ /* wait for peer's response for our delete request, but set a timeout */
+ return SUCCESS;
+ }
+ if (!this->rekeyed)
+ { /* invoke ike_down() hook if SA has not been rekeyed */
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ /* completed, delete IKE_SA by returning DESTROY_ME */
+ return DESTROY_ME;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_delete_t *this)
+{
+ return IKE_DELETE;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_delete_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->simultaneous = FALSE;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_delete_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_delete_t *this = malloc_thing(private_ike_delete_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->rekeyed = FALSE;
+ this->simultaneous = FALSE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_delete.h b/src/libcharon/sa/tasks/ike_delete.h
new file mode 100644
index 000000000..82782f393
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_delete.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_delete ike_delete
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_DELETE_H_
+#define IKE_DELETE_H_
+
+typedef struct ike_delete_t ike_delete_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_delete, delete an IKE_SA.
+ */
+struct ike_delete_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_delete task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if we initiate the delete
+ * @return ike_delete task to handle by the task_manager
+ */
+ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_dpd.c b/src/libcharon/sa/tasks/ike_dpd.c
new file mode 100644
index 000000000..4c6ba7662
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_dpd.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_dpd.h"
+
+#include <daemon.h>
+
+
+typedef struct private_ike_dpd_t private_ike_dpd_t;
+
+/**
+ * Private members of a ike_dpd_t task.
+ */
+struct private_ike_dpd_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_dpd_t public;
+};
+
+/**
+ * Implementation of task_t.build for initiator
+ * Implementation of task_t.process for responder
+ */
+static status_t return_need_more(private_ike_dpd_t *this, message_t *message)
+{
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ * Implementation of task_t.build for responder
+ */
+static status_t return_success(private_ike_dpd_t *this, message_t *message)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_dpd_t *this)
+{
+ return IKE_DPD;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_dpd_t *this, ike_sa_t *ike_sa)
+{
+
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_dpd_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_dpd_t *ike_dpd_create(bool initiator)
+{
+ private_ike_dpd_t *this = malloc_thing(private_ike_dpd_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))return_need_more;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))return_success;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))return_success;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))return_need_more;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_dpd.h b/src/libcharon/sa/tasks/ike_dpd.h
new file mode 100644
index 000000000..36388d15b
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_dpd.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_dpd ike_dpd
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_DPD_H_
+#define IKE_DPD_H_
+
+typedef struct ike_dpd_t ike_dpd_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_dpd, detects dead peers.
+ *
+ * The DPD task actually does nothing, as a DPD has no associated payloads.
+ */
+struct ike_dpd_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_dpd task.
+ *
+ * @param initiator TRUE if thask is the original initator
+ * @return ike_dpd task to handle by the task_manager
+ */
+ike_dpd_t *ike_dpd_create(bool initiator);
+
+#endif /** IKE_DPD_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c
new file mode 100644
index 000000000..5eb33b540
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_init.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_init.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <crypto/diffie_hellman.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+
+/** maximum retries to do with cookies/other dh groups */
+#define MAX_RETRIES 5
+
+typedef struct private_ike_init_t private_ike_init_t;
+
+/**
+ * Private members of a ike_init_t task.
+ */
+struct private_ike_init_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_init_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * IKE config to establish
+ */
+ ike_cfg_t *config;
+
+ /**
+ * diffie hellman group to use
+ */
+ diffie_hellman_group_t dh_group;
+
+ /**
+ * diffie hellman key exchange
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * Keymat derivation (from IKE_SA)
+ */
+ keymat_t *keymat;
+
+ /**
+ * nonce chosen by us
+ */
+ chunk_t my_nonce;
+
+ /**
+ * nonce chosen by peer
+ */
+ chunk_t other_nonce;
+
+ /**
+ * Negotiated proposal used for IKE_SA
+ */
+ proposal_t *proposal;
+
+ /**
+ * Old IKE_SA which gets rekeyed
+ */
+ ike_sa_t *old_sa;
+
+ /**
+ * cookie received from responder
+ */
+ chunk_t cookie;
+
+ /**
+ * retries done so far after failure (cookie or bad dh group)
+ */
+ u_int retry;
+};
+
+/**
+ * build the payloads for the message
+ */
+static void build_payloads(private_ike_init_t *this, message_t *message)
+{
+ sa_payload_t *sa_payload;
+ ke_payload_t *ke_payload;
+ nonce_payload_t *nonce_payload;
+ linked_list_t *proposal_list;
+ ike_sa_id_t *id;
+ proposal_t *proposal;
+ iterator_t *iterator;
+
+ id = this->ike_sa->get_id(this->ike_sa);
+
+ this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
+
+ if (this->initiator)
+ {
+ proposal_list = this->config->get_proposals(this->config);
+ if (this->old_sa)
+ {
+ /* include SPI of new IKE_SA when we are rekeying */
+ iterator = proposal_list->create_iterator(proposal_list, TRUE);
+ while (iterator->iterate(iterator, (void**)&proposal))
+ {
+ proposal->set_spi(proposal, id->get_initiator_spi(id));
+ }
+ iterator->destroy(iterator);
+ }
+
+ sa_payload = sa_payload_create_from_proposal_list(proposal_list);
+ proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
+ }
+ else
+ {
+ if (this->old_sa)
+ {
+ /* include SPI of new IKE_SA when we are rekeying */
+ this->proposal->set_spi(this->proposal, id->get_responder_spi(id));
+ }
+ sa_payload = sa_payload_create_from_proposal(this->proposal);
+ }
+ message->add_payload(message, (payload_t*)sa_payload);
+
+ nonce_payload = nonce_payload_create();
+ nonce_payload->set_nonce(nonce_payload, this->my_nonce);
+ ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
+
+ if (this->old_sa)
+ { /* payload order differs if we are rekeying */
+ message->add_payload(message, (payload_t*)nonce_payload);
+ message->add_payload(message, (payload_t*)ke_payload);
+ }
+ else
+ {
+ message->add_payload(message, (payload_t*)ke_payload);
+ message->add_payload(message, (payload_t*)nonce_payload);
+ }
+}
+
+/**
+ * Read payloads from message
+ */
+static void process_payloads(private_ike_init_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case SECURITY_ASSOCIATION:
+ {
+ sa_payload_t *sa_payload = (sa_payload_t*)payload;
+ linked_list_t *proposal_list;
+ bool private;
+
+ proposal_list = sa_payload->get_proposals(sa_payload);
+ private = this->ike_sa->supports_extension(this->ike_sa,
+ EXT_STRONGSWAN);
+ this->proposal = this->config->select_proposal(this->config,
+ proposal_list, private);
+ proposal_list->destroy_offset(proposal_list,
+ offsetof(proposal_t, destroy));
+ break;
+ }
+ case KEY_EXCHANGE:
+ {
+ ke_payload_t *ke_payload = (ke_payload_t*)payload;
+
+ this->dh_group = ke_payload->get_dh_group_number(ke_payload);
+ if (!this->initiator)
+ {
+ this->dh = this->keymat->create_dh(this->keymat,
+ this->dh_group);
+ }
+ if (this->dh)
+ {
+ this->dh->set_other_public_value(this->dh,
+ ke_payload->get_key_exchange_data(ke_payload));
+ }
+ break;
+ }
+ case NONCE:
+ {
+ nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
+
+ this->other_nonce = nonce_payload->get_nonce(nonce_payload);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_init_t *this, message_t *message)
+{
+ rng_t *rng;
+
+ this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ if (this->retry >= MAX_RETRIES)
+ {
+ DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES);
+ return FAILED;
+ }
+
+ /* if the DH group is set via use_dh_group(), we already have a DH object */
+ if (!this->dh)
+ {
+ this->dh_group = this->config->get_dh_group(this->config);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ if (!this->dh)
+ {
+ DBG1(DBG_IKE, "configured DH group %N not supported",
+ diffie_hellman_group_names, this->dh_group);
+ return FAILED;
+ }
+ }
+
+ /* generate nonce only when we are trying the first time */
+ if (this->my_nonce.ptr == NULL)
+ {
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "error generating nonce");
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
+ rng->destroy(rng);
+ }
+
+ if (this->cookie.ptr)
+ {
+ message->add_notify(message, FALSE, COOKIE, this->cookie);
+ }
+
+ build_payloads(this, message);
+
+#ifdef ME
+ {
+ chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
+ if (connect_id.ptr)
+ {
+ message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
+ }
+ }
+#endif /* ME */
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_init_t *this, message_t *message)
+{
+ rng_t *rng;
+
+ this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "error generating nonce");
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
+ rng->destroy(rng);
+
+#ifdef ME
+ {
+ notify_payload_t *notify = message->get_notify(message, ME_CONNECTID);
+ if (notify)
+ {
+ chunk_t connect_id = notify->get_notification_data(notify);
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
+ charon->connect_manager->stop_checks(charon->connect_manager,
+ connect_id);
+ }
+ }
+#endif /* ME */
+
+ process_payloads(this, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Derive the keymat for the IKE_SA
+ */
+static bool derive_keys(private_ike_init_t *this,
+ chunk_t nonce_i, chunk_t nonce_r)
+{
+ keymat_t *old_keymat;
+ pseudo_random_function_t prf_alg = PRF_UNDEFINED;
+ chunk_t skd = chunk_empty;
+ ike_sa_id_t *id;
+
+ id = this->ike_sa->get_id(this->ike_sa);
+ if (this->old_sa)
+ {
+ /* rekeying: Include old SKd, use old PRF, apply SPI */
+ old_keymat = this->old_sa->get_keymat(this->old_sa);
+ prf_alg = old_keymat->get_skd(old_keymat, &skd);
+ if (this->initiator)
+ {
+ id->set_responder_spi(id, this->proposal->get_spi(this->proposal));
+ }
+ else
+ {
+ id->set_initiator_spi(id, this->proposal->get_spi(this->proposal));
+ }
+ }
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ nonce_i, nonce_r, id, prf_alg, skd))
+ {
+ return FALSE;
+ }
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
+ nonce_i, nonce_r, this->old_sa);
+ return TRUE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_init_t *this, message_t *message)
+{
+ /* check if we have everything we need */
+ if (this->proposal == NULL ||
+ this->other_nonce.len == 0 || this->my_nonce.len == 0)
+ {
+ DBG1(DBG_IKE, "received proposals inacceptable");
+ message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ return FAILED;
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ if (this->dh == NULL ||
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
+ {
+ u_int16_t group;
+
+ if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
+ &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
+ diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
+ this->dh_group = group;
+ group = htons(group);
+ message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
+ chunk_from_thing(group));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "no acceptable proposal found");
+ }
+ return FAILED;
+ }
+
+ if (!derive_keys(this, this->other_nonce, this->my_nonce))
+ {
+ DBG1(DBG_IKE, "key derivation failed");
+ message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ return FAILED;
+ }
+ build_payloads(this, message);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_init_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ /* check for erronous notifies */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ case INVALID_KE_PAYLOAD:
+ {
+ chunk_t data;
+ diffie_hellman_group_t bad_group;
+
+ bad_group = this->dh_group;
+ data = notify->get_notification_data(notify);
+ this->dh_group = ntohs(*((u_int16_t*)data.ptr));
+ DBG1(DBG_IKE, "peer didn't accept DH group %N, "
+ "it requested %N", diffie_hellman_group_names,
+ bad_group, diffie_hellman_group_names, this->dh_group);
+
+ if (this->old_sa == NULL)
+ { /* reset the IKE_SA if we are not rekeying */
+ this->ike_sa->reset(this->ike_sa);
+ }
+
+ enumerator->destroy(enumerator);
+ this->retry++;
+ return NEED_MORE;
+ }
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ /* skip, handled in ike_natd_t */
+ break;
+ case MULTIPLE_AUTH_SUPPORTED:
+ /* handled in ike_auth_t */
+ break;
+ case COOKIE:
+ {
+ chunk_free(&this->cookie);
+ this->cookie = chunk_clone(notify->get_notification_data(notify));
+ this->ike_sa->reset(this->ike_sa);
+ enumerator->destroy(enumerator);
+ DBG2(DBG_IKE, "received %N notify", notify_type_names, type);
+ this->retry++;
+ return NEED_MORE;
+ }
+ default:
+ {
+ if (type < 16383)
+ {
+ DBG1(DBG_IKE, "received %N notify error",
+ notify_type_names, type);
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ DBG2(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ break;
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ process_payloads(this, message);
+
+ /* check if we have everything */
+ if (this->proposal == NULL ||
+ this->other_nonce.len == 0 || this->my_nonce.len == 0)
+ {
+ DBG1(DBG_IKE, "peers proposal selection invalid");
+ return FAILED;
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ if (this->dh == NULL ||
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
+ {
+ DBG1(DBG_IKE, "peer DH group selection invalid");
+ return FAILED;
+ }
+
+ if (!derive_keys(this, this->my_nonce, this->other_nonce))
+ {
+ DBG1(DBG_IKE, "key derivation failed");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_init_t *this)
+{
+ return IKE_INIT;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static chunk_t get_lower_nonce(private_ike_init_t *this)
+{
+ if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
+ min(this->my_nonce.len, this->other_nonce.len)) < 0)
+ {
+ return this->my_nonce;
+ }
+ else
+ {
+ return this->other_nonce;
+ }
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
+{
+ DESTROY_IF(this->proposal);
+ chunk_free(&this->other_nonce);
+
+ this->ike_sa = ike_sa;
+ this->proposal = NULL;
+ DESTROY_IF(this->dh);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_init_t *this)
+{
+ DESTROY_IF(this->dh);
+ DESTROY_IF(this->proposal);
+ chunk_free(&this->my_nonce);
+ chunk_free(&this->other_nonce);
+ chunk_free(&this->cookie);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
+{
+ private_ike_init_t *this = malloc_thing(private_ike_init_t);
+
+ this->public.get_lower_nonce = (chunk_t(*)(ike_init_t*))get_lower_nonce;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->dh_group = MODP_NONE;
+ this->dh = NULL;
+ this->keymat = ike_sa->get_keymat(ike_sa);
+ this->my_nonce = chunk_empty;
+ this->other_nonce = chunk_empty;
+ this->cookie = chunk_empty;
+ this->proposal = NULL;
+ this->config = NULL;
+ this->old_sa = old_sa;
+ this->retry = 0;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_init.h b/src/libcharon/sa/tasks/ike_init.h
new file mode 100644
index 000000000..7bd784cff
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_init.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_init ike_init
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_INIT_H_
+#define IKE_INIT_H_
+
+typedef struct ike_init_t ike_init_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type IKE_INIT, creates an IKE_SA without authentication.
+ *
+ * The authentication of is handle in the ike_auth task.
+ */
+struct ike_init_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Get the lower of the two nonces, used for rekey collisions.
+ *
+ * @return lower nonce
+ */
+ chunk_t (*get_lower_nonce) (ike_init_t *this);
+};
+
+/**
+ * Create a new IKE_INIT task.
+ *
+ * @param ike_sa IKE_SA this task works for (new one when rekeying)
+ * @param initiator TRUE if thask is the original initator
+ * @param old_sa old IKE_SA when we are rekeying
+ * @return ike_init task to handle by the task_manager
+ */
+ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa);
+
+#endif /** IKE_INIT_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_me.c b/src/libcharon/sa/tasks/ike_me.c
new file mode 100644
index 000000000..2d2847ae0
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_me.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright (C) 2007-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 "ike_me.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <config/peer_cfg.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <encoding/payloads/endpoint_notify.h>
+#include <processing/jobs/mediation_job.h>
+
+#define ME_CONNECTID_LEN 4
+#define ME_CONNECTKEY_LEN 16
+
+typedef struct private_ike_me_t private_ike_me_t;
+
+/**
+ * Private members of a ike_me_t task.
+ */
+struct private_ike_me_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_me_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Is this a mediation connection?
+ */
+ bool mediation;
+
+ /**
+ * Is this the response from another peer?
+ */
+ bool response;
+
+ /**
+ * Gathered endpoints
+ */
+ linked_list_t *local_endpoints;
+
+ /**
+ * Parsed endpoints
+ */
+ linked_list_t *remote_endpoints;
+
+ /**
+ * Did the peer request a callback?
+ */
+ bool callback;
+
+ /**
+ * Did the connect fail?
+ */
+ bool failed;
+
+ /**
+ * Was there anything wrong with the payloads?
+ */
+ bool invalid_syntax;
+
+ /**
+ * The requested peer
+ */
+ identification_t *peer_id;
+ /**
+ * Received ID used for connectivity checks
+ */
+ chunk_t connect_id;
+
+ /**
+ * Received key used for connectivity checks
+ */
+ chunk_t connect_key;
+
+ /**
+ * Peer config of the mediated connection
+ */
+ peer_cfg_t *mediated_cfg;
+
+};
+
+/**
+ * Adds a list of endpoints as notifies to a given message
+ */
+static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
+{
+ iterator_t *iterator;
+ endpoint_notify_t *endpoint;
+
+ iterator = endpoints->create_iterator(endpoints, TRUE);
+ while (iterator->iterate(iterator, (void**)&endpoint))
+ {
+ message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Gathers endpoints and adds them to the current message
+ */
+static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ host_t *addr, *host;
+ u_int16_t port;
+
+ /* get the port that is used to communicate with the ms */
+ host = this->ike_sa->get_my_host(this->ike_sa);
+ port = host->get_port(host);
+
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&addr))
+ {
+ host = addr->clone(addr);
+ host->set_port(host, port);
+
+ this->local_endpoints->insert_last(this->local_endpoints,
+ endpoint_notify_create_from_host(HOST, host, NULL));
+
+ host->destroy(host);
+ }
+ enumerator->destroy(enumerator);
+
+ host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
+ if (host)
+ {
+ this->local_endpoints->insert_last(this->local_endpoints,
+ endpoint_notify_create_from_host(SERVER_REFLEXIVE, host,
+ this->ike_sa->get_my_host(this->ike_sa)));
+ }
+
+ add_endpoints_to_message(message, this->local_endpoints);
+}
+
+/**
+ * read notifys from message and evaluate them
+ */
+static void process_payloads(private_ike_me_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != NOTIFY)
+ {
+ continue;
+ }
+
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ switch (notify->get_notify_type(notify))
+ {
+ case ME_CONNECT_FAILED:
+ {
+ DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify");
+ this->failed = TRUE;
+ break;
+ }
+ case ME_MEDIATION:
+ {
+ DBG2(DBG_IKE, "received ME_MEDIATION notify");
+ this->mediation = TRUE;
+ break;
+ }
+ case ME_ENDPOINT:
+ {
+ endpoint_notify_t *endpoint;
+ endpoint = endpoint_notify_create_from_payload(notify);
+ if (!endpoint)
+ {
+ DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify");
+ break;
+ }
+ DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H",
+ me_endpoint_type_names, endpoint->get_type(endpoint),
+ endpoint->get_host(endpoint));
+
+ this->remote_endpoints->insert_last(this->remote_endpoints,
+ endpoint);
+ break;
+ }
+ case ME_CALLBACK:
+ {
+ DBG2(DBG_IKE, "received ME_CALLBACK notify");
+ this->callback = TRUE;
+ break;
+ }
+ case ME_CONNECTID:
+ {
+ chunk_free(&this->connect_id);
+ this->connect_id = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id);
+ break;
+ }
+ case ME_CONNECTKEY:
+ {
+ chunk_free(&this->connect_key);
+ this->connect_key = chunk_clone(notify->get_notification_data(notify));
+ DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key);
+ break;
+ }
+ case ME_RESPONSE:
+ {
+ DBG2(DBG_IKE, "received ME_RESPONSE notify");
+ this->response = TRUE;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ {
+ peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ DBG2(DBG_IKE, "adding ME_MEDIATION");
+ message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
+ }
+ else
+ {
+ return SUCCESS;
+ }
+ break;
+ }
+ case IKE_AUTH:
+ {
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
+ {
+ endpoint_notify_t *endpoint;
+ endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
+ NULL, NULL);
+ message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
+ endpoint->destroy(endpoint);
+ }
+ break;
+ }
+ case ME_CONNECT:
+ {
+ rng_t *rng;
+ id_payload_t *id_payload;
+ id_payload = id_payload_create_from_identification(ID_PEER,
+ this->peer_id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT");
+ return FAILED;
+ }
+ if (!this->response)
+ {
+ /* only the initiator creates a connect ID. the responder
+ * returns the connect ID that it received from the initiator */
+ rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id);
+ }
+ rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key);
+ rng->destroy(rng);
+
+ message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
+ message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
+
+ if (this->response)
+ {
+ message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
+ }
+ else
+ {
+ /* FIXME: should we make this configurable? */
+ message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
+ }
+
+ gather_and_add_endpoints(this, message);
+
+ break;
+ }
+ default:
+ break;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case ME_CONNECT:
+ {
+ id_payload_t *id_payload;
+ id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
+ ", aborting");
+ break;
+ }
+ this->peer_id = id_payload->get_identification(id_payload);
+
+ process_payloads(this, message);
+
+ if (this->callback)
+ {
+ DBG1(DBG_IKE, "received ME_CALLBACK for '%Y'", this->peer_id);
+ break;
+ }
+
+ if (!this->connect_id.ptr)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
+ ", aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+
+ if (!this->connect_key.ptr)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY "
+ "notify, aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+
+ if (!this->remote_endpoints->get_count(this->remote_endpoints))
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
+ "payloads, aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+
+ DBG1(DBG_IKE, "received ME_CONNECT");
+ break;
+ }
+ default:
+ break;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case ME_CONNECT:
+ {
+ if (this->invalid_syntax)
+ {
+ message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
+ break;
+ }
+
+ if (this->callback)
+ {
+ /* we got a callback from the mediation server, initiate the
+ * queued mediated connecction */
+ charon->connect_manager->check_and_initiate(
+ charon->connect_manager,
+ this->ike_sa->get_id(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
+ return SUCCESS;
+ }
+
+ if (this->response)
+ {
+ /* FIXME: handle result of set_responder_data
+ * as initiator, upon receiving a response from another peer,
+ * update the checklist and start sending checks */
+ charon->connect_manager->set_responder_data(
+ charon->connect_manager,
+ this->connect_id, this->connect_key,
+ this->remote_endpoints);
+ }
+ else
+ {
+ /* FIXME: handle result of set_initiator_data
+ * as responder, create a checklist with the initiator's data */
+ charon->connect_manager->set_initiator_data(
+ charon->connect_manager,
+ this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
+ this->connect_id, this->connect_key,
+ this->remote_endpoints, FALSE);
+ if (this->ike_sa->respond(this->ike_sa, this->peer_id,
+ this->connect_id) != SUCCESS)
+ {
+ return FAILED;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ {
+ process_payloads(this, message);
+ if (!this->mediation)
+ {
+ DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting");
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+ case IKE_AUTH:
+ {
+ process_payloads(this, message);
+ /* FIXME: we should update the server reflexive endpoint somehow,
+ * if mobike notices a change */
+ endpoint_notify_t *reflexive;
+ if (this->remote_endpoints->get_first(this->remote_endpoints,
+ (void**)&reflexive) == SUCCESS &&
+ reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
+ { /* FIXME: should we accept this endpoint even if we did not send
+ * a request? */
+ host_t *endpoint = reflexive->get_host(reflexive);
+ endpoint = endpoint->clone(endpoint);
+ this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint);
+ }
+ break;
+ }
+ case ME_CONNECT:
+ {
+ process_payloads(this, message);
+
+ if (this->failed)
+ {
+ DBG1(DBG_IKE, "peer '%Y' is not online", this->peer_id);
+ /* FIXME: notify the mediated connection (job?) */
+ }
+ else
+ {
+ if (this->response)
+ {
+ /* FIXME: handle result of set_responder_data. */
+ /* as responder, we update the checklist and start sending
+ * checks */
+ charon->connect_manager->set_responder_data(
+ charon->connect_manager, this->connect_id,
+ this->connect_key, this->local_endpoints);
+ }
+ else
+ {
+ /* FIXME: handle result of set_initiator_data */
+ /* as initiator, we create a checklist and set the
+ * initiator's data */
+ charon->connect_manager->set_initiator_data(
+ charon->connect_manager,
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->peer_id, this->connect_id, this->connect_key,
+ this->local_endpoints, TRUE);
+ /* FIXME: also start a timer for the whole transaction
+ * (maybe within the connect_manager?) */
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.build for initiator (mediation server)
+ */
+static status_t build_i_ms(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case ME_CONNECT:
+ {
+ id_payload_t *id_payload;
+ id_payload = id_payload_create_from_identification(ID_PEER,
+ this->peer_id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ if (this->callback)
+ {
+ message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
+ }
+ else
+ {
+ if (this->response)
+ {
+ message->add_notify(message, FALSE, ME_RESPONSE,
+ chunk_empty);
+ }
+ message->add_notify(message, FALSE, ME_CONNECTID,
+ this->connect_id);
+ message->add_notify(message, FALSE, ME_CONNECTKEY,
+ this->connect_key);
+ add_endpoints_to_message(message, this->remote_endpoints);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder (mediation server)
+ */
+static status_t process_r_ms(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ {
+ /* FIXME: we should check for SA* and TS* payloads. if there are
+ * any, send NO_ADDITIONAL_SAS back and delete this SA */
+ process_payloads(this, message);
+ return this->mediation ? NEED_MORE : SUCCESS;
+ }
+ case IKE_AUTH:
+ {
+ /* FIXME: we should check whether the current peer_config is
+ * configured as mediation connection */
+ process_payloads(this, message);
+ break;
+ }
+ case CREATE_CHILD_SA:
+ {
+ /* FIXME: if this is not to rekey the IKE SA we have to return a
+ * NO_ADDITIONAL_SAS and then delete the SA */
+ break;
+ }
+ case ME_CONNECT:
+ {
+ id_payload_t *id_payload;
+ id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
+ ", aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+ this->peer_id = id_payload->get_identification(id_payload);
+
+ process_payloads(this, message);
+
+ if (!this->connect_id.ptr)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
+ ", aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+
+ if (!this->connect_key.ptr)
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify"
+ ", aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+
+ if (!this->remote_endpoints->get_count(this->remote_endpoints))
+ {
+ DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
+ "payloads, aborting");
+ this->invalid_syntax = TRUE;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder (mediation server)
+ */
+static status_t build_r_ms(private_ike_me_t *this, message_t *message)
+{
+ switch(message->get_exchange_type(message))
+ {
+ case IKE_SA_INIT:
+ {
+ message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
+ return NEED_MORE;
+ }
+ case IKE_AUTH:
+ {
+ endpoint_notify_t *endpoint;
+ if (this->remote_endpoints->get_first(this->remote_endpoints,
+ (void**)&endpoint) == SUCCESS &&
+ endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
+ {
+ host_t *host = this->ike_sa->get_other_host(this->ike_sa);
+ DBG2(DBG_IKE, "received request for a server reflexive "
+ "endpoint sending: %#H", host);
+ endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
+ host, NULL);
+ message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
+ endpoint->destroy(endpoint);
+ }
+ this->ike_sa->act_as_mediation_server(this->ike_sa);
+ break;
+ }
+ case ME_CONNECT:
+ {
+ if (this->invalid_syntax)
+ {
+ message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
+ break;
+ }
+
+ ike_sa_id_t *peer_sa;
+ if (this->callback)
+ {
+ peer_sa = charon->mediation_manager->check_and_register(
+ charon->mediation_manager, this->peer_id,
+ this->ike_sa->get_other_id(this->ike_sa));
+ }
+ else
+ {
+ peer_sa = charon->mediation_manager->check(
+ charon->mediation_manager, this->peer_id);
+ }
+
+ if (!peer_sa)
+ {
+ /* the peer is not online */
+ message->add_notify(message, TRUE, ME_CONNECT_FAILED,
+ chunk_empty);
+ break;
+ }
+
+ job_t *job = (job_t*)mediation_job_create(this->peer_id,
+ this->ike_sa->get_other_id(this->ike_sa), this->connect_id,
+ this->connect_key, this->remote_endpoints, this->response);
+ charon->processor->queue_job(charon->processor, job);
+ break;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator (mediation server)
+ */
+static status_t process_i_ms(private_ike_me_t *this, message_t *message)
+{
+ /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
+ * here if the responding peer is not able to proceed. in this case we shall
+ * notify the initiating peer with a ME_CONNECT request containing only a
+ * ME_CONNECT_FAILED */
+ return SUCCESS;
+}
+
+/**
+ * Implementation of ike_me.connect
+ */
+static void me_connect(private_ike_me_t *this, identification_t *peer_id)
+{
+ this->peer_id = peer_id->clone(peer_id);
+}
+
+/**
+ * Implementation of ike_me.respond
+ */
+static void me_respond(private_ike_me_t *this, identification_t *peer_id,
+ chunk_t connect_id)
+{
+ this->peer_id = peer_id->clone(peer_id);
+ this->connect_id = chunk_clone(connect_id);
+ this->response = TRUE;
+}
+
+/**
+ * Implementation of ike_me.callback
+ */
+static void me_callback(private_ike_me_t *this, identification_t *peer_id)
+{
+ this->peer_id = peer_id->clone(peer_id);
+ this->callback = TRUE;
+}
+
+/**
+ * Implementation of ike_me.relay
+ */
+static void relay(private_ike_me_t *this, identification_t *requester,
+ chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response)
+{
+ this->peer_id = requester->clone(requester);
+ this->connect_id = chunk_clone(connect_id);
+ this->connect_key = chunk_clone(connect_key);
+
+ this->remote_endpoints->destroy_offset(this->remote_endpoints,
+ offsetof(endpoint_notify_t, destroy));
+ this->remote_endpoints = endpoints->clone_offset(endpoints,
+ offsetof(endpoint_notify_t, clone));
+
+ this->response = response;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_me_t *this)
+{
+ return IKE_ME;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_me_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_me_t *this)
+{
+ DESTROY_IF(this->peer_id);
+
+ chunk_free(&this->connect_id);
+ chunk_free(&this->connect_key);
+
+ this->local_endpoints->destroy_offset(this->local_endpoints,
+ offsetof(endpoint_notify_t, destroy));
+ this->remote_endpoints->destroy_offset(this->remote_endpoints,
+ offsetof(endpoint_notify_t, destroy));
+
+ DESTROY_IF(this->mediated_cfg);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_me_t *this = malloc_thing(private_ike_me_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
+ {
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+ }
+ else
+ {
+ /* mediation server */
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms;
+ }
+ }
+
+ this->public.connect = (void(*)(ike_me_t*,identification_t*))me_connect;
+ this->public.respond = (void(*)(ike_me_t*,identification_t*,chunk_t))me_respond;
+ this->public.callback = (void(*)(ike_me_t*,identification_t*))me_callback;
+ this->public.relay = (void(*)(ike_me_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+
+ this->peer_id = NULL;
+ this->connect_id = chunk_empty;
+ this->connect_key = chunk_empty;
+ this->local_endpoints = linked_list_create();
+ this->remote_endpoints = linked_list_create();
+ this->mediation = FALSE;
+ this->response = FALSE;
+ this->callback = FALSE;
+ this->failed = FALSE;
+ this->invalid_syntax = FALSE;
+
+ this->mediated_cfg = NULL;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_me.h b/src/libcharon/sa/tasks/ike_me.h
new file mode 100644
index 000000000..31285a426
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_me.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_me ike_me
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_ME_H_
+#define IKE_ME_H_
+
+typedef struct ike_me_t ike_me_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type IKE_ME, detects and handles IKE-ME extensions.
+ *
+ * This tasks handles the ME_MEDIATION Notify exchange to setup a mediation
+ * connection, allows to initiate mediated connections using ME_CONNECT
+ * exchanges and to request reflexive addresses from the mediation server using
+ * ME_ENDPOINT notifies.
+ *
+ * @note This task has to be activated before the IKE_AUTH task, because that
+ * task generates the IKE_SA_INIT message so that no more payloads can be added
+ * to it afterwards.
+ */
+struct ike_me_t {
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Initiates a connection with another peer (i.e. sends a ME_CONNECT
+ * to the mediation server)
+ *
+ * @param peer_id ID of the other peer (gets cloned)
+ */
+ void (*connect)(ike_me_t *this, identification_t *peer_id);
+
+ /**
+ * Responds to a ME_CONNECT from another peer (i.e. sends a ME_CONNECT
+ * to the mediation server)
+ *
+ * Data gets cloned.
+ *
+ * @param peer_id ID of the other peer
+ * @param connect_id the connect ID as provided by the initiator
+ */
+ void (*respond)(ike_me_t *this, identification_t *peer_id,
+ chunk_t connect_id);
+
+ /**
+ * Sends a ME_CALLBACK to a peer that previously requested some other peer.
+ *
+ * @param peer_id ID of the other peer (gets cloned)
+ */
+ void (*callback)(ike_me_t *this, identification_t *peer_id);
+
+ /**
+ * Relays data to another peer (i.e. sends a ME_CONNECT to the peer)
+ *
+ * Data gets cloned.
+ *
+ * @param requester ID of the requesting peer
+ * @param connect_id content of the ME_CONNECTID notify
+ * @param connect_key content of the ME_CONNECTKEY notify
+ * @param endpoints endpoints
+ * @param response TRUE if this is a response
+ */
+ void (*relay)(ike_me_t *this, identification_t *requester,
+ chunk_t connect_id, chunk_t connect_key,
+ linked_list_t *endpoints, bool response);
+};
+
+/**
+ * Create a new ike_me task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task is initiated by us
+ * @return ike_me task to be handled by the task_manager
+ */
+ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_ME_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_mobike.c b/src/libcharon/sa/tasks/ike_mobike.c
new file mode 100644
index 000000000..a62886f02
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_mobike.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_mobike.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <sa/tasks/ike_natd.h>
+#include <encoding/payloads/notify_payload.h>
+
+#define COOKIE2_SIZE 16
+#define MAX_ADDITIONAL_ADDRS 8
+
+typedef struct private_ike_mobike_t private_ike_mobike_t;
+
+/**
+ * Private members of a ike_mobike_t task.
+ */
+struct private_ike_mobike_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_mobike_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * cookie2 value to verify new addresses
+ */
+ chunk_t cookie2;
+
+ /**
+ * NAT discovery reusing the IKE_NATD task
+ */
+ ike_natd_t *natd;
+
+ /**
+ * use task to update addresses
+ */
+ bool update;
+
+ /**
+ * do routability check
+ */
+ bool check;
+
+ /**
+ * include address list update
+ */
+ bool address;
+};
+
+/**
+ * flush the IKE_SAs list of additional addresses
+ */
+static void flush_additional_addresses(private_ike_mobike_t *this)
+{
+ iterator_t *iterator;
+ host_t *host;
+
+ iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
+ while (iterator->iterate(iterator, (void**)&host))
+ {
+ iterator->remove(iterator);
+ host->destroy(host);
+ }
+ iterator->destroy(iterator);
+}
+
+
+/**
+ * read notifys from message and evaluate them
+ */
+static void process_payloads(private_ike_mobike_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool first = TRUE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ int family = AF_INET;
+ notify_payload_t *notify;
+ chunk_t data;
+ host_t *host;
+
+ if (payload->get_type(payload) != NOTIFY)
+ {
+ continue;
+ }
+ notify = (notify_payload_t*)payload;
+ switch (notify->get_notify_type(notify))
+ {
+ case MOBIKE_SUPPORTED:
+ {
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (!this->initiator &&
+ peer_cfg && !peer_cfg->use_mobike(peer_cfg))
+ {
+ DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "peer supports MOBIKE");
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
+ }
+ break;
+ }
+ case COOKIE2:
+ {
+ chunk_free(&this->cookie2);
+ this->cookie2 = chunk_clone(notify->get_notification_data(notify));
+ break;
+ }
+ case ADDITIONAL_IP6_ADDRESS:
+ {
+ family = AF_INET6;
+ /* fall through */
+ }
+ case ADDITIONAL_IP4_ADDRESS:
+ {
+ if (first)
+ { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
+ flush_additional_addresses(this);
+ first = FALSE;
+ }
+ data = notify->get_notification_data(notify);
+ host = host_create_from_chunk(family, data, 0);
+ DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
+ this->ike_sa->add_additional_address(this->ike_sa, host);
+ break;
+ }
+ case UPDATE_SA_ADDRESSES:
+ {
+ this->update = TRUE;
+ break;
+ }
+ case NO_ADDITIONAL_ADDRESSES:
+ {
+ flush_additional_addresses(this);
+ break;
+ }
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ {
+ /* NAT check in this MOBIKE exchange, create subtask for it */
+ if (this->natd == NULL)
+ {
+ this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
+ */
+static void build_address_list(private_ike_mobike_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ host_t *host, *me;
+ notify_type_t type;
+ int added = 0;
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&host))
+ {
+ if (me->ip_equals(me, host))
+ { /* "ADDITIONAL" means do not include IKE_SAs host */
+ continue;
+ }
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ type = ADDITIONAL_IP4_ADDRESS;
+ break;
+ case AF_INET6:
+ type = ADDITIONAL_IP6_ADDRESS;
+ break;
+ default:
+ continue;
+ }
+ message->add_notify(message, FALSE, type, host->get_address(host));
+ if (++added >= MAX_ADDITIONAL_ADDRS)
+ { /* limit number of notifys, some implementations do not like too
+ * many of them (f.e. strongSwan ;-) */
+ break;
+ }
+ }
+ if (!added)
+ {
+ message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * build a cookie and add it to the message
+ */
+static void build_cookie(private_ike_mobike_t *this, message_t *message)
+{
+ rng_t *rng;
+
+ chunk_free(&this->cookie2);
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (rng)
+ {
+ rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2);
+ rng->destroy(rng);
+ message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ }
+}
+
+/**
+ * update addresses of associated CHILD_SAs
+ */
+static void update_children(private_ike_mobike_t *this)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ if (child_sa->update(child_sa,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->ike_sa->rekey_child_sa(this->ike_sa,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Apply port of old address if it equals new, port otherwise
+ */
+static void apply_port(private_ike_mobike_t *this, host_t *host, host_t *old,
+ u_int16_t port)
+{
+ if (host->ip_equals(host, old))
+ {
+ host->set_port(host, old->get_port(old));
+ }
+ else
+ {
+ if (port == IKEV2_UDP_PORT)
+ {
+ host->set_port(host, IKEV2_NATT_PORT);
+ }
+ else
+ {
+ host->set_port(host, port);
+ }
+ }
+}
+
+/**
+ * Implementation of ike_mobike_t.transmit
+ */
+static void transmit(private_ike_mobike_t *this, packet_t *packet)
+{
+ host_t *me, *other, *me_old, *other_old;
+ iterator_t *iterator;
+ ike_cfg_t *ike_cfg;
+ packet_t *copy;
+
+ if (!this->check)
+ {
+ return;
+ }
+
+ me_old = this->ike_sa->get_my_host(this->ike_sa);
+ other_old = this->ike_sa->get_other_host(this->ike_sa);
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+
+ me = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, other_old, NULL);
+ if (me)
+ {
+ apply_port(this, me, me_old, ike_cfg->get_my_port(ike_cfg));
+ DBG1(DBG_IKE, "checking original path %#H - %#H", me, other_old);
+ copy = packet->clone(packet);
+ copy->set_source(copy, me);
+ charon->sender->send(charon->sender, copy);
+ }
+
+ iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
+ while (iterator->iterate(iterator, (void**)&other))
+ {
+ me = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, other, NULL);
+ if (me)
+ {
+ if (me->get_family(me) != other->get_family(other))
+ {
+ me->destroy(me);
+ continue;
+ }
+ /* reuse port for an active address, 4500 otherwise */
+ apply_port(this, me, me_old, ike_cfg->get_my_port(ike_cfg));
+ other = other->clone(other);
+ apply_port(this, other, other_old, ike_cfg->get_other_port(ike_cfg));
+ DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
+ copy = packet->clone(packet);
+ copy->set_source(copy, me);
+ copy->set_destination(copy, other);
+ charon->sender->send(charon->sender, copy);
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_mobike_t *this, message_t *message)
+{
+ if (message->get_message_id(message) == 1)
+ { /* only in first IKE_AUTH */
+ message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
+ build_address_list(this, message);
+ }
+ else if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ host_t *old, *new;
+
+ /* we check if the existing address is still valid */
+ old = message->get_source(message);
+ new = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ message->get_destination(message), old);
+ if (new)
+ {
+ if (!new->ip_equals(new, old))
+ {
+ new->set_port(new, old->get_port(old));
+ message->set_source(message, new);
+ }
+ else
+ {
+ new->destroy(new);
+ }
+ }
+ if (this->update)
+ {
+ message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty);
+ build_cookie(this, message);
+ update_children(this);
+ }
+ if (this->address)
+ {
+ build_address_list(this, message);
+ }
+ if (this->natd)
+ {
+ this->natd->task.build(&this->natd->task, message);
+ }
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_mobike_t *this, message_t *message)
+{
+ if (message->get_message_id(message) == 1)
+ { /* only first IKE_AUTH */
+ process_payloads(this, message);
+ }
+ else if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ process_payloads(this, message);
+ if (this->update)
+ {
+ host_t *me, *other;
+
+ me = message->get_destination(message);
+ other = message->get_source(message);
+ this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
+ this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
+ }
+
+ if (this->natd)
+ {
+ this->natd->task.process(&this->natd->task, message);
+ }
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_mobike_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ {
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
+ {
+ message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
+ build_address_list(this, message);
+ }
+ return SUCCESS;
+ }
+ else if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ if (this->natd)
+ {
+ this->natd->task.build(&this->natd->task, message);
+ }
+ if (this->cookie2.ptr)
+ {
+ message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ chunk_free(&this->cookie2);
+ }
+ if (this->update)
+ {
+ update_children(this);
+ }
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_mobike_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ {
+ process_payloads(this, message);
+ return SUCCESS;
+ }
+ else if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ u_int32_t updates = this->ike_sa->get_pending_updates(this->ike_sa) - 1;
+ this->ike_sa->set_pending_updates(this->ike_sa, updates);
+ if (updates > 0)
+ {
+ /* newer update queued, ignore this one */
+ return SUCCESS;
+ }
+ if (this->cookie2.ptr)
+ { /* check cookie if we included one */
+ chunk_t cookie2;
+
+ cookie2 = this->cookie2;
+ this->cookie2 = chunk_empty;
+ process_payloads(this, message);
+ if (!chunk_equals(cookie2, this->cookie2))
+ {
+ chunk_free(&cookie2);
+ DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
+ return FAILED;
+ }
+ chunk_free(&cookie2);
+ }
+ else
+ {
+ process_payloads(this, message);
+ }
+ if (this->natd)
+ {
+ this->natd->task.process(&this->natd->task, message);
+ if (this->natd->has_mapping_changed(this->natd))
+ {
+ /* force an update if mappings have changed */
+ this->update = this->check = TRUE;
+ DBG1(DBG_IKE, "detected changes in NAT mappings, "
+ "initiating MOBIKE update");
+ }
+ }
+ if (this->update)
+ {
+ /* update again, as NAT state may have changed */
+ update_children(this);
+ }
+ if (this->check)
+ {
+ host_t *me_new, *me_old, *other_new, *other_old;
+
+ me_new = message->get_destination(message);
+ other_new = message->get_source(message);
+ me_old = this->ike_sa->get_my_host(this->ike_sa);
+ other_old = this->ike_sa->get_other_host(this->ike_sa);
+
+ if (!me_new->equals(me_new, me_old))
+ {
+ this->update = TRUE;
+ this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new));
+ }
+ if (!other_new->equals(other_new, other_old))
+ {
+ this->update = TRUE;
+ this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new));
+ }
+ if (this->update)
+ {
+ /* start the update with the same task */
+ this->check = FALSE;
+ this->address = FALSE;
+ if (this->natd)
+ {
+ this->natd->task.destroy(&this->natd->task);
+ }
+ this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ this->ike_sa->set_pending_updates(this->ike_sa, 1);
+ return NEED_MORE;
+ }
+ }
+ return SUCCESS;
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of ike_mobike_t.roam.
+ */
+static void roam(private_ike_mobike_t *this, bool address)
+{
+ this->check = TRUE;
+ this->address = address;
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+}
+
+/**
+ * Implementation of ike_mobike_t.dpd
+ */
+static void dpd(private_ike_mobike_t *this)
+{
+ if (!this->natd)
+ {
+ this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ }
+ this->address = FALSE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+}
+
+/**
+ * Implementation of ike_mobike_t.is_probing.
+ */
+static bool is_probing(private_ike_mobike_t *this)
+{
+ return this->check;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_mobike_t *this)
+{
+ return IKE_MOBIKE;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
+{
+ chunk_free(&this->cookie2);
+ this->ike_sa = ike_sa;
+ if (this->natd)
+ {
+ this->natd->task.migrate(&this->natd->task, ike_sa);
+ }
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_mobike_t *this)
+{
+ chunk_free(&this->cookie2);
+ if (this->natd)
+ {
+ this->natd->task.destroy(&this->natd->task);
+ }
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
+
+ this->public.roam = (void(*)(ike_mobike_t*,bool))roam;
+ this->public.dpd = (void(*)(ike_mobike_t*))dpd;
+ this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit;
+ this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->update = FALSE;
+ this->check = FALSE;
+ this->address = TRUE;
+ this->cookie2 = chunk_empty;
+ this->natd = NULL;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_mobike.h b/src/libcharon/sa/tasks/ike_mobike.h
new file mode 100644
index 000000000..05b2224d1
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_mobike.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_mobike ike_mobike
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_MOBIKE_H_
+#define IKE_MOBIKE_H_
+
+typedef struct ike_mobike_t ike_mobike_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+#include <network/packet.h>
+
+/**
+ * Task of type ike_mobike, detects and handles MOBIKE extension.
+ *
+ * The MOBIKE extension is defined in RFC4555. It allows to update IKE
+ * and IPsec tunnel addresses.
+ * This tasks handles the MOBIKE_SUPPORTED notify exchange to detect MOBIKE
+ * support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional
+ * endpoints and handles the UPDATE_SA_ADDRESS notify to finally update
+ * endpoints.
+ */
+struct ike_mobike_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Use the task to roam to other addresses.
+ *
+ * @param address TRUE to include address list update
+ */
+ void (*roam)(ike_mobike_t *this, bool address);
+
+ /**
+ * Use the task for a DPD check which detects changes in NAT mappings.
+ */
+ void (*dpd)(ike_mobike_t *this);
+
+ /**
+ * Transmision hook, called by task manager.
+ *
+ * The task manager calls this hook whenever it transmits a packet. It
+ * allows the mobike task to send the packet on multiple paths to do path
+ * probing.
+ *
+ * @param packet the packet to transmit
+ */
+ void (*transmit)(ike_mobike_t *this, packet_t *packet);
+
+ /**
+ * Check if this task is probing for routability.
+ *
+ * @return TRUE if task is probing
+ */
+ bool (*is_probing)(ike_mobike_t *this);
+};
+
+/**
+ * Create a new ike_mobike task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if taks is initiated by us
+ * @return ike_mobike task to handle by the task_manager
+ */
+ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_MOBIKE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_natd.c b/src/libcharon/sa/tasks/ike_natd.c
new file mode 100644
index 000000000..9ea20ba36
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_natd.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2006-2007 Martin Willi
+ * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_natd.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <config/peer_cfg.h>
+#include <crypto/hashers/hasher.h>
+#include <encoding/payloads/notify_payload.h>
+
+
+typedef struct private_ike_natd_t private_ike_natd_t;
+
+/**
+ * Private members of a ike_natd_t task.
+ */
+struct private_ike_natd_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_natd_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Hasher used to build NAT detection hashes
+ */
+ hasher_t *hasher;
+
+ /**
+ * Did we process any NAT detection notifys for a source address?
+ */
+ bool src_seen;
+
+ /**
+ * Did we process any NAT detection notifys for a destination address?
+ */
+ bool dst_seen;
+
+ /**
+ * Have we found a matching source address NAT hash?
+ */
+ bool src_matched;
+
+ /**
+ * Have we found a matching destination address NAT hash?
+ */
+ bool dst_matched;
+
+ /**
+ * whether NAT mappings for our NATed address has changed
+ */
+ bool mapping_changed;
+};
+
+
+/**
+ * Build NAT detection hash for a host
+ */
+static chunk_t generate_natd_hash(private_ike_natd_t *this,
+ ike_sa_id_t *ike_sa_id, host_t *host)
+{
+ chunk_t natd_chunk, spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk;
+ chunk_t natd_hash;
+ u_int64_t spi_i, spi_r;
+ u_int16_t port;
+
+ /* prepare all required chunks */
+ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
+ spi_i_chunk.ptr = (void*)&spi_i;
+ spi_i_chunk.len = sizeof(spi_i);
+ spi_r_chunk.ptr = (void*)&spi_r;
+ spi_r_chunk.len = sizeof(spi_r);
+ port = htons(host->get_port(host));
+ port_chunk.ptr = (void*)&port;
+ port_chunk.len = sizeof(port);
+ addr_chunk = host->get_address(host);
+
+ /* natd_hash = SHA1( spi_i | spi_r | address | port ) */
+ natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk);
+ this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash);
+ DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
+ DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
+
+ chunk_free(&natd_chunk);
+ return natd_hash;
+}
+
+/**
+ * build a faked NATD payload to enforce UDP encap
+ */
+static chunk_t generate_natd_hash_faked(private_ike_natd_t *this)
+{
+ rng_t *rng;
+ chunk_t chunk;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "unable to get random bytes for NATD fake");
+ return chunk_empty;
+ }
+ rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk);
+ rng->destroy(rng);
+ return chunk;
+}
+
+/**
+ * Build a NAT detection notify payload.
+ */
+static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
+ notify_type_t type, host_t *host)
+{
+ chunk_t hash;
+ notify_payload_t *notify;
+ ike_sa_id_t *ike_sa_id;
+ ike_cfg_t *config;
+
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (config->force_encap(config) && type == NAT_DETECTION_SOURCE_IP)
+ {
+ hash = generate_natd_hash_faked(this);
+ }
+ else
+ {
+ hash = generate_natd_hash(this, ike_sa_id, host);
+ }
+ notify = notify_payload_create();
+ notify->set_notify_type(notify, type);
+ notify->set_notification_data(notify, hash);
+ chunk_free(&hash);
+
+ return notify;
+}
+
+/**
+ * read notifys from message and evaluate them
+ */
+static void process_payloads(private_ike_natd_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ notify_payload_t *notify;
+ chunk_t hash, src_hash, dst_hash;
+ ike_sa_id_t *ike_sa_id;
+ host_t *me, *other;
+ ike_cfg_t *config;
+
+ /* Precompute NAT-D hashes for incoming NAT notify comparison */
+ ike_sa_id = message->get_ike_sa_id(message);
+ me = message->get_destination(message);
+ other = message->get_source(message);
+ dst_hash = generate_natd_hash(this, ike_sa_id, me);
+ src_hash = generate_natd_hash(this, ike_sa_id, other);
+
+ DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
+ DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != NOTIFY)
+ {
+ continue;
+ }
+ notify = (notify_payload_t*)payload;
+ switch (notify->get_notify_type(notify))
+ {
+ case NAT_DETECTION_DESTINATION_IP:
+ {
+ this->dst_seen = TRUE;
+ hash = notify->get_notification_data(notify);
+ if (!this->dst_matched)
+ {
+ DBG3(DBG_IKE, "received dst_hash %B", &hash);
+ if (chunk_equals(hash, dst_hash))
+ {
+ this->dst_matched = TRUE;
+ }
+ }
+ /* RFC4555 says we should also compare against IKE_SA_INIT
+ * NATD payloads, but this does not work: We are running
+ * there at port 500, but use 4500 afterwards... */
+ if (message->get_exchange_type(message) == INFORMATIONAL &&
+ this->initiator && !this->dst_matched)
+ {
+ this->mapping_changed = this->ike_sa->has_mapping_changed(
+ this->ike_sa, hash);
+ }
+ break;
+ }
+ case NAT_DETECTION_SOURCE_IP:
+ {
+ this->src_seen = TRUE;
+ if (!this->src_matched)
+ {
+ hash = notify->get_notification_data(notify);
+ DBG3(DBG_IKE, "received src_hash %B", &hash);
+ if (chunk_equals(hash, src_hash))
+ {
+ this->src_matched = TRUE;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ chunk_free(&src_hash);
+ chunk_free(&dst_hash);
+
+ if (this->src_seen && this->dst_seen)
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_NATT);
+
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
+ !this->dst_matched);
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
+ !this->src_matched);
+ config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (this->dst_matched && this->src_matched &&
+ config->force_encap(config))
+ {
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
+ }
+ }
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_natd_t *this, message_t *message)
+{
+ process_payloads(this, message);
+
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+
+#ifdef ME
+ /* if we are on a mediated connection we have already switched to
+ * port 4500 and the correct destination port is already configured,
+ * therefore we must not switch again */
+ if (peer_cfg->get_mediated_by(peer_cfg))
+ {
+ return SUCCESS;
+ }
+#endif /* ME */
+
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) ||
+#ifdef ME
+ /* if we are on a mediation connection we switch to port 4500 even
+ * if no NAT is detected. */
+ peer_cfg->is_mediation(peer_cfg) ||
+#endif /* ME */
+ /* if peer supports NAT-T, we switch to port 4500 even
+ * if no NAT is detected. MOBIKE requires this. */
+ (peer_cfg->use_mobike(peer_cfg) &&
+ this->ike_sa->supports_extension(this->ike_sa, EXT_NATT)))
+ {
+ host_t *me, *other;
+
+ /* do not switch if we have a custom port from mobike/NAT */
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ if (me->get_port(me) == IKEV2_UDP_PORT)
+ {
+ me->set_port(me, IKEV2_NATT_PORT);
+ }
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ if (other->get_port(other) == IKEV2_UDP_PORT)
+ {
+ other->set_port(other, IKEV2_NATT_PORT);
+ }
+ }
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_natd_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ enumerator_t *enumerator;
+ ike_cfg_t *ike_cfg;
+ host_t *host;
+
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
+ return NEED_MORE;
+ }
+
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+
+ /* destination is always set */
+ host = message->get_destination(message);
+ notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+
+ /* source may be any, we have 3 possibilities to get our source address:
+ * 1. It is defined in the config => use the one of the IKE_SA
+ * 2. We do a routing lookup in the kernel interface
+ * 3. Include all possbile addresses
+ */
+ host = message->get_source(message);
+ if (!host->is_anyaddr(host))
+ { /* 1. */
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+ }
+ else
+ {
+ host = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ this->ike_sa->get_other_host(this->ike_sa), NULL);
+ if (host)
+ { /* 2. */
+ host->set_port(host, ike_cfg->get_my_port(ike_cfg));
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+ host->destroy(host);
+ }
+ else
+ { /* 3. */
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&host))
+ {
+ /* apply port 500 to host, but work on a copy */
+ host = host->clone(host);
+ host->set_port(host, ike_cfg->get_my_port(ike_cfg));
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
+ host->destroy(host);
+ message->add_payload(message, (payload_t*)notify);
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_natd_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ host_t *me, *other;
+
+ /* only add notifies on successfull responses. */
+ if (message->get_exchange_type(message) == IKE_SA_INIT &&
+ message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+ {
+ return SUCCESS;
+ }
+
+ if (this->src_seen && this->dst_seen)
+ {
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
+ return SUCCESS;
+ }
+
+ /* initiator seems to support NAT detection, add response */
+ me = message->get_source(message);
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me);
+ message->add_payload(message, (payload_t*)notify);
+
+ other = message->get_destination(message);
+ notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other);
+ message->add_payload(message, (payload_t*)notify);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_natd_t *this, message_t *message)
+{
+ process_payloads(this, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_natd_t *this)
+{
+ return IKE_NATD;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->src_seen = FALSE;
+ this->dst_seen = FALSE;
+ this->src_matched = FALSE;
+ this->dst_matched = FALSE;
+ this->mapping_changed = FALSE;
+}
+
+/**
+ * Implementation of ike_natd_t.has_mapping_changed
+ */
+static bool has_mapping_changed(private_ike_natd_t *this)
+{
+ return this->mapping_changed;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_natd_t *this)
+{
+ DESTROY_IF(this->hasher);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_natd_t *this = malloc_thing(private_ike_natd_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->public.has_mapping_changed = (bool(*)(ike_natd_t*))has_mapping_changed;
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ this->src_seen = FALSE;
+ this->dst_seen = FALSE;
+ this->src_matched = FALSE;
+ this->dst_matched = FALSE;
+ this->mapping_changed = FALSE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_natd.h b/src/libcharon/sa/tasks/ike_natd.h
new file mode 100644
index 000000000..97b652ead
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_natd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_natd ike_natd
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_NATD_H_
+#define IKE_NATD_H_
+
+typedef struct ike_natd_t ike_natd_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange.
+ */
+struct ike_natd_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Check if the NAT mapping has changed for our address.
+ *
+ * MOBIKE uses NAT payloads in DPD to detect changes in the NAT mappings.
+ *
+ * @return TRUE if mappings have changed
+ */
+ bool (*has_mapping_changed)(ike_natd_t *this);
+};
+
+/**
+ * Create a new ike_natd task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the original initator
+ * @return ike_natd task to handle by the task_manager
+ */
+ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_NATD_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_reauth.c b/src/libcharon/sa/tasks/ike_reauth.c
new file mode 100644
index 000000000..ac89c358b
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_reauth.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_reauth.h"
+
+#include <daemon.h>
+#include <sa/tasks/ike_delete.h>
+
+
+typedef struct private_ike_reauth_t private_ike_reauth_t;
+
+/**
+ * Private members of a ike_reauth_t task.
+ */
+struct private_ike_reauth_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_reauth_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * reused ike_delete task
+ */
+ ike_delete_t *ike_delete;
+};
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_ike_reauth_t *this, message_t *message)
+{
+ return this->ike_delete->task.build(&this->ike_delete->task, message);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_reauth_t *this, message_t *message)
+{
+ ike_sa_t *new;
+ host_t *host;
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ peer_cfg_t *peer_cfg;
+
+ /* process delete response first */
+ this->ike_delete->task.process(&this->ike_delete->task, message);
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+
+ /* reauthenticate only if we have children */
+ iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
+ if (iterator->get_count(iterator) == 0
+#ifdef ME
+ /* we allow peers to reauth mediation connections (without children) */
+ && !peer_cfg->is_mediation(peer_cfg)
+#endif /* ME */
+ )
+ {
+ DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
+ iterator->destroy(iterator);
+ return FAILED;
+ }
+
+ new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
+
+ new->set_peer_cfg(new, peer_cfg);
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ new->set_other_host(new, host->clone(host));
+ host = this->ike_sa->get_my_host(this->ike_sa);
+ new->set_my_host(new, host->clone(host));
+ /* if we already have a virtual IP, we reuse it */
+ host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (host)
+ {
+ new->set_virtual_ip(new, TRUE, host);
+ }
+
+#ifdef ME
+ /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ if (new->initiate(new, NULL, 0, NULL, NULL) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+ return FAILED;
+ }
+ }
+#endif /* ME */
+
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_ROUTED:
+ {
+ /* move routed child directly */
+ iterator->remove(iterator);
+ new->add_child_sa(new, child_sa);
+ break;
+ }
+ default:
+ {
+ /* initiate/queue all child SAs */
+ child_cfg_t *child_cfg = child_sa->get_config(child_sa);
+ child_cfg->get_ref(child_cfg);
+ if (new->initiate(new, child_cfg, 0, NULL, NULL) == DESTROY_ME)
+ {
+ iterator->destroy(iterator);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+ return FAILED;
+ }
+ break;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+
+ /* we always return failed to delete the obsolete IKE_SA */
+ return FAILED;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_reauth_t *this)
+{
+ return IKE_REAUTH;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_reauth_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa);
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_reauth_t *this)
+{
+ this->ike_delete->task.destroy(&this->ike_delete->task);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa)
+{
+ private_ike_reauth_t *this = malloc_thing(private_ike_reauth_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+
+ this->ike_sa = ike_sa;
+ this->ike_delete = ike_delete_create(ike_sa, TRUE);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_reauth.h b/src/libcharon/sa/tasks/ike_reauth.h
new file mode 100644
index 000000000..5e97b719c
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_reauth.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_reauth ike_reauth
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_REAUTH_H_
+#define IKE_REAUTH_H_
+
+typedef struct ike_reauth_t ike_reauth_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_reauth, reestablishes an IKE_SA.
+ */
+struct ike_reauth_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_reauth task.
+ *
+ * This task is initiator only.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @return ike_reauth task to handle by the task_manager
+ */
+ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa);
+
+#endif /** IKE_REAUTH_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/tasks/ike_rekey.c
new file mode 100644
index 000000000..a2275e796
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_rekey.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_rekey.h"
+
+#include <daemon.h>
+#include <encoding/payloads/notify_payload.h>
+#include <sa/tasks/ike_init.h>
+#include <sa/tasks/ike_delete.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+
+
+typedef struct private_ike_rekey_t private_ike_rekey_t;
+
+/**
+ * Private members of a ike_rekey_t task.
+ */
+struct private_ike_rekey_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_rekey_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * New IKE_SA which replaces the current one
+ */
+ ike_sa_t *new_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * the IKE_INIT task which is reused to simplify rekeying
+ */
+ ike_init_t *ike_init;
+
+ /**
+ * IKE_DELETE task to delete the old IKE_SA after rekeying was successful
+ */
+ ike_delete_t *ike_delete;
+
+ /**
+ * colliding task detected by the task manager
+ */
+ task_t *collision;
+};
+
+/**
+ * Implementation of task_t.build for initiator, after rekeying
+ */
+static status_t build_i_delete(private_ike_rekey_t *this, message_t *message)
+{
+ /* update exchange type to INFORMATIONAL for the delete */
+ message->set_exchange_type(message, INFORMATIONAL);
+
+ return this->ike_delete->task.build(&this->ike_delete->task, message);
+}
+
+/**
+ * Implementation of task_t.process for initiator, after rekeying
+ */
+static status_t process_i_delete(private_ike_rekey_t *this, message_t *message)
+{
+ return this->ike_delete->task.process(&this->ike_delete->task, message);
+}
+
+/**
+ * Implementation of task_t.build for initiator
+ */
+static status_t build_i(private_ike_rekey_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+ host_t *other_host;
+
+ /* create new SA only on first try */
+ if (this->new_sa == NULL)
+ {
+ this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+ TRUE);
+
+ 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->ike_init = ike_init_create(this->new_sa, TRUE, this->ike_sa);
+ this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
+ }
+ this->ike_init->task.build(&this->ike_init->task, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_rekey_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
+ {
+ DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting");
+ return NEED_MORE;
+ }
+
+ iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_CREATED:
+ case CHILD_REKEYING:
+ case CHILD_DELETING:
+ /* we do not allow rekeying while we have children in-progress */
+ DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open");
+ iterator->destroy(iterator);
+ return NEED_MORE;
+ default:
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+ FALSE);
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
+ this->ike_init = ike_init_create(this->new_sa, FALSE, this->ike_sa);
+ this->ike_init->task.process(&this->ike_init->task, message);
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_rekey_t *this, message_t *message)
+{
+ if (this->new_sa == NULL)
+ {
+ /* IKE_SA/a CHILD_SA is in an inacceptable state, deny rekeying */
+ message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ return SUCCESS;
+ }
+
+ if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
+ {
+ return SUCCESS;
+ }
+
+ this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
+ this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_rekey_t *this, message_t *message)
+{
+ if (message->get_notify(message, NO_ADDITIONAL_SAS))
+ {
+ DBG1(DBG_IKE, "peer seems to not support IKE rekeying, "
+ "starting reauthentication");
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ return SUCCESS;
+ }
+
+ switch (this->ike_init->task.process(&this->ike_init->task, message))
+ {
+ case FAILED:
+ /* rekeying failed, fallback to old SA */
+ if (!(this->collision && (
+ this->collision->get_type(this->collision) == IKE_DELETE ||
+ this->collision->get_type(this->collision) == IKE_REAUTH)))
+ {
+ job_t *job;
+ u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+ job = (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), FALSE);
+ DBG1(DBG_IKE, "IKE_SA rekeying failed, "
+ "trying again in %d seconds", retry);
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->scheduler->schedule_job(charon->scheduler, job, retry);
+ }
+ return SUCCESS;
+ case NEED_MORE:
+ /* bad dh group, try again */
+ this->ike_init->task.migrate(&this->ike_init->task, this->new_sa);
+ return NEED_MORE;
+ default:
+ break;
+ }
+
+ this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ /* check for collisions */
+ if (this->collision &&
+ this->collision->get_type(this->collision) == IKE_REKEY)
+ {
+ chunk_t this_nonce, other_nonce;
+ host_t *host;
+ private_ike_rekey_t *other = (private_ike_rekey_t*)this->collision;
+
+ this_nonce = this->ike_init->get_lower_nonce(this->ike_init);
+ other_nonce = other->ike_init->get_lower_nonce(other->ike_init);
+
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ /* peer should delete this SA. Add a timeout just in case. */
+ job_t *job = (job_t*)delete_ike_sa_job_create(
+ other->new_sa->get_id(other->new_sa), TRUE);
+ charon->scheduler->schedule_job(charon->scheduler, job, 10);
+ DBG1(DBG_IKE, "IKE_SA rekey collision won, deleting rekeyed IKE_SA");
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa);
+ other->new_sa = NULL;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "IKE_SA rekey collision lost, deleting redundant IKE_SA");
+ /* apply host for a proper delete */
+ host = this->ike_sa->get_my_host(this->ike_sa);
+ this->new_sa->set_my_host(this->new_sa, host->clone(host));
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ this->new_sa->set_other_host(this->new_sa, host->clone(host));
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ if (this->new_sa->delete(this->new_sa) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, this->new_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, this->new_sa);
+ }
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ /* inherit to other->new_sa in destroy() */
+ this->new_sa = other->new_sa;
+ other->new_sa = NULL;
+ return SUCCESS;
+ }
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ }
+
+ /* rekeying successful, delete the IKE_SA using a subtask */
+ this->ike_delete = ike_delete_create(this->ike_sa, TRUE);
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete;
+
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_rekey_t *this)
+{
+ return IKE_REKEY;
+}
+
+static void collide(private_ike_rekey_t* this, task_t *other)
+{
+ DESTROY_IF(this->collision);
+ this->collision = other;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa)
+{
+ if (this->ike_init)
+ {
+ this->ike_init->task.destroy(&this->ike_init->task);
+ }
+ if (this->ike_delete)
+ {
+ this->ike_delete->task.destroy(&this->ike_delete->task);
+ }
+ if (this->new_sa)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ this->new_sa);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ }
+ DESTROY_IF(this->collision);
+
+ this->collision = NULL;
+ this->ike_sa = ike_sa;
+ this->new_sa = NULL;
+ this->ike_init = NULL;
+ this->ike_delete = NULL;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_rekey_t *this)
+{
+ if (this->new_sa)
+ {
+ if (this->new_sa->get_state(this->new_sa) == IKE_ESTABLISHED &&
+ this->new_sa->inherit(this->new_sa, this->ike_sa) != DESTROY_ME)
+ {
+ /* invoke hook if rekeying was successful */
+ charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ this->new_sa);
+ }
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ }
+ if (this->ike_init)
+ {
+ this->ike_init->task.destroy(&this->ike_init->task);
+ }
+ if (this->ike_delete)
+ {
+ this->ike_delete->task.destroy(&this->ike_delete->task);
+ }
+ DESTROY_IF(this->collision);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_rekey_t *this = malloc_thing(private_ike_rekey_t);
+
+ this->public.collide = (void(*)(ike_rekey_t*,task_t*))collide;
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->new_sa = NULL;
+ this->ike_init = NULL;
+ this->ike_delete = NULL;
+ this->initiator = initiator;
+ this->collision = NULL;
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/tasks/ike_rekey.h b/src/libcharon/sa/tasks/ike_rekey.h
new file mode 100644
index 000000000..1c9550768
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_rekey.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ike_rekey ike_rekey
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_REKEY_H_
+#define IKE_REKEY_H_
+
+typedef struct ike_rekey_t ike_rekey_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type IKE_REKEY, rekey an established IKE_SA.
+ */
+struct ike_rekey_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Register a rekeying task which collides with this one.
+ *
+ * If two peers initiate rekeying at the same time, the collision must
+ * be handled gracefully. The task manager is aware of what exchanges
+ * are going on and notifies the outgoing task by passing the incoming.
+ *
+ * @param other incoming task
+ */
+ void (*collide)(ike_rekey_t* this, task_t *other);
+};
+
+/**
+ * Create a new IKE_REKEY task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE for initiator, FALSE for responder
+ * @return IKE_REKEY task to handle by the task_manager
+ */
+ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_REKEY_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_vendor.c b/src/libcharon/sa/tasks/ike_vendor.c
new file mode 100644
index 000000000..7c435b6d1
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_vendor.c
@@ -0,0 +1,139 @@
+/*
+ * 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 "ike_vendor.h"
+
+#include <daemon.h>
+#include <encoding/payloads/vendor_id_payload.h>
+
+typedef struct private_ike_vendor_t private_ike_vendor_t;
+
+/**
+ * Private data of an ike_vendor_t object.
+ */
+struct private_ike_vendor_t {
+
+ /**
+ * Public ike_vendor_t interface.
+ */
+ ike_vendor_t public;
+
+ /**
+ * Associated IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the inititator of this task
+ */
+ bool initiator;
+};
+
+/**
+ * strongSwan specific vendor ID without version, MD5("strongSwan")
+ */
+static chunk_t strongswan_vid = chunk_from_chars(
+ 0x88,0x2f,0xe5,0x6d,0x6f,0xd2,0x0d,0xbc,
+ 0x22,0x51,0x61,0x3b,0x2e,0xbe,0x5b,0xeb
+);
+
+METHOD(task_t, build, status_t,
+ private_ike_vendor_t *this, message_t *message)
+{
+ if (lib->settings->get_bool(lib->settings,
+ "charon.send_vendor_id", FALSE))
+ {
+ vendor_id_payload_t *vid;
+
+ vid = vendor_id_payload_create_data(chunk_clone(strongswan_vid));
+ message->add_payload(message, &vid->payload_interface);
+ }
+
+ return this->initiator ? NEED_MORE : SUCCESS;
+}
+
+METHOD(task_t, process, status_t,
+ private_ike_vendor_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == VENDOR_ID)
+ {
+ vendor_id_payload_t *vid;
+ chunk_t data;
+
+ vid = (vendor_id_payload_t*)payload;
+ data = vid->get_data(vid);
+
+ if (chunk_equals(data, strongswan_vid))
+ {
+ DBG1(DBG_IKE, "received strongSwan vendor id");
+ this->ike_sa->enable_extension(this->ike_sa, EXT_STRONGSWAN);
+ }
+ else
+ {
+ DBG1(DBG_ENC, "received unknown vendor id: %#B", &data);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return this->initiator ? SUCCESS : NEED_MORE;
+}
+
+METHOD(task_t, migrate, void,
+ private_ike_vendor_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_ike_vendor_t *this)
+{
+ return IKE_VENDOR;
+}
+
+METHOD(task_t, destroy, void,
+ private_ike_vendor_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_vendor_t *this;
+
+ INIT(this,
+ .public.task = {
+ .build = _build,
+ .process = _process,
+ .migrate = _migrate,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .initiator = initiator,
+ .ike_sa = ike_sa,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/tasks/ike_vendor.h b/src/libcharon/sa/tasks/ike_vendor.h
new file mode 100644
index 000000000..dcdd37424
--- /dev/null
+++ b/src/libcharon/sa/tasks/ike_vendor.h
@@ -0,0 +1,49 @@
+/*
+ * 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 ike_vendor ike_vendor
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_VENDOR_H_
+#define IKE_VENDOR_H_
+
+typedef struct ike_vendor_t ike_vendor_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Vendor ID processing task.
+ */
+struct ike_vendor_t {
+
+ /**
+ * Implements task interface.
+ */
+ task_t task;
+};
+
+/**
+ * Create a ike_vendor instance.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the original initator
+ */
+ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_VENDOR_H_ @}*/
diff --git a/src/libcharon/sa/tasks/task.c b/src/libcharon/sa/tasks/task.c
new file mode 100644
index 000000000..0d7383141
--- /dev/null
+++ b/src/libcharon/sa/tasks/task.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "task.h"
+
+#ifdef ME
+ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ "IKE_INIT",
+ "IKE_NATD",
+ "IKE_MOBIKE",
+ "IKE_AUTHENTICATE",
+ "IKE_AUTH_LIFETIME",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
+ "IKE_CONFIG",
+ "IKE_REKEY",
+ "IKE_REAUTH",
+ "IKE_DELETE",
+ "IKE_DPD",
+ "IKE_VENDOR",
+ "IKE_ME",
+ "CHILD_CREATE",
+ "CHILD_DELETE",
+ "CHILD_REKEY",
+);
+#else
+ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ "IKE_INIT",
+ "IKE_NATD",
+ "IKE_MOBIKE",
+ "IKE_AUTHENTICATE",
+ "IKE_AUTH_LIFETIME",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
+ "IKE_CONFIG",
+ "IKE_REKEY",
+ "IKE_REAUTH",
+ "IKE_DELETE",
+ "IKE_DPD",
+ "IKE_VENDOR",
+ "CHILD_CREATE",
+ "CHILD_DELETE",
+ "CHILD_REKEY",
+);
+#endif /* ME */
diff --git a/src/libcharon/sa/tasks/task.h b/src/libcharon/sa/tasks/task.h
new file mode 100644
index 000000000..4468f2ebe
--- /dev/null
+++ b/src/libcharon/sa/tasks/task.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2006 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 task task
+ * @{ @ingroup tasks
+ */
+
+#ifndef TASK_H_
+#define TASK_H_
+
+typedef enum task_type_t task_type_t;
+typedef struct task_t task_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <encoding/message.h>
+
+/**
+ * Different kinds of tasks.
+ */
+enum task_type_t {
+ /** establish an unauthenticated IKE_SA */
+ IKE_INIT,
+ /** detect NAT situation */
+ IKE_NATD,
+ /** handle MOBIKE stuff */
+ IKE_MOBIKE,
+ /** authenticate the initiated IKE_SA */
+ IKE_AUTHENTICATE,
+ /** AUTH_LIFETIME negotiation, RFC4478 */
+ IKE_AUTH_LIFETIME,
+ /** certificate processing before authentication (certreqs, cert parsing) */
+ IKE_CERT_PRE,
+ /** certificate processing after authentication (certs payload generation) */
+ IKE_CERT_POST,
+ /** Configuration payloads, virtual IP and such */
+ IKE_CONFIG,
+ /** rekey an IKE_SA */
+ IKE_REKEY,
+ /** reestablish a complete IKE_SA */
+ IKE_REAUTH,
+ /** delete an IKE_SA */
+ IKE_DELETE,
+ /** liveness check */
+ IKE_DPD,
+ /** Vendor ID processing */
+ IKE_VENDOR,
+#ifdef ME
+ /** handle ME stuff */
+ IKE_ME,
+#endif /* ME */
+ /** establish a CHILD_SA within an IKE_SA */
+ CHILD_CREATE,
+ /** delete an established CHILD_SA */
+ CHILD_DELETE,
+ /** rekey an CHILD_SA */
+ CHILD_REKEY,
+};
+
+/**
+ * enum names for task_type_t.
+ */
+extern enum_name_t *task_type_names;
+
+/**
+ * Interface for a task, an operation handled within exchanges.
+ *
+ * A task is an elemantary operation. It may be handled by a single or by
+ * multiple exchanges. An exchange may even complete multiple tasks.
+ * A task has a build() and an process() operation. The build() operation
+ * creates payloads and adds it to the message. The process() operation
+ * inspects a message and handles its payloads. An initiator of an exchange
+ * first calls build() to build the request, and processes the response message
+ * with the process() method.
+ * A responder does the opposite; it calls process() first to handle an incoming
+ * request and secondly calls build() to build an appropriate response.
+ * Both methods return either SUCCESS, NEED_MORE or FAILED. A SUCCESS indicates
+ * that the task completed, even when the task completed unsuccesfully. The
+ * manager then removes the task from the list. A NEED_MORE is returned when
+ * the task needs further build()/process() calls to complete, the manager
+ * leaves the taks in the queue. A returned FAILED indicates a critical failure.
+ * The manager closes the IKE_SA whenever a task returns FAILED.
+ */
+struct task_t {
+
+ /**
+ * Build a request or response message for this task.
+ *
+ * @param message message to add payloads to
+ * @return
+ * - FAILED if a critical error occured
+ * - DESTROY_ME if IKE_SA has been properly deleted
+ * - NEED_MORE if another call to build/process needed
+ * - SUCCESS if task completed
+ */
+ status_t (*build) (task_t *this, message_t *message);
+
+ /**
+ * Process a request or response message for this task.
+ *
+ * @param message message to read payloads from
+ * @return
+ * - FAILED if a critical error occured
+ * - DESTROY_ME if IKE_SA has been properly deleted
+ * - NEED_MORE if another call to build/process needed
+ * - SUCCESS if task completed
+ */
+ status_t (*process) (task_t *this, message_t *message);
+
+ /**
+ * Get the type of the task implementation.
+ */
+ task_type_t (*get_type) (task_t *this);
+
+ /**
+ * Migrate a task to a new IKE_SA.
+ *
+ * After migrating a task, it goes back to a state where it can be
+ * used again to initate an exchange. This is useful when a task
+ * has to get migrated to a new IKE_SA.
+ * A special usage is when a INVALID_KE_PAYLOAD is received. A call
+ * to reset resets the task, but uses another DH group for the next
+ * try.
+ * The ike_sa is the new IKE_SA this task belongs to and operates on.
+ *
+ * @param ike_sa new IKE_SA this task works for
+ */
+ void (*migrate) (task_t *this, ike_sa_t *ike_sa);
+
+ /**
+ * Destroys a task_t object.
+ */
+ void (*destroy) (task_t *this);
+};
+
+#endif /** TASK_H_ @}*/
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
new file mode 100644
index 000000000..878170c83
--- /dev/null
+++ b/src/libcharon/sa/trap_manager.c
@@ -0,0 +1,403 @@
+/*
+ * 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 "trap_manager.h"
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_trap_manager_t private_trap_manager_t;
+typedef struct trap_listener_t trap_listener_t;
+
+/**
+ * listener to track acquires
+ */
+struct trap_listener_t {
+
+ /**
+ * Implements listener interface
+ */
+ listener_t listener;
+
+ /**
+ * points to trap_manager
+ */
+ private_trap_manager_t *traps;
+};
+
+/**
+ * Private data of an trap_manager_t object.
+ */
+struct private_trap_manager_t {
+
+ /**
+ * Public trap_manager_t interface.
+ */
+ trap_manager_t public;
+
+ /**
+ * Installed traps, as entry_t
+ */
+ linked_list_t *traps;
+
+ /**
+ * read write lock for traps list
+ */
+ rwlock_t *lock;
+
+ /**
+ * listener to track acquiring IKE_SAs
+ */
+ trap_listener_t listener;
+};
+
+/**
+ * A installed trap entry
+ */
+typedef struct {
+ /** ref to peer_cfg to initiate */
+ peer_cfg_t *peer_cfg;
+ /** ref to instanciated CHILD_SA */
+ child_sa_t *child_sa;
+ /** pending IKE_SA connecting upon acquire */
+ ike_sa_t *pending;
+} entry_t;
+
+/**
+ * actually uninstall and destroy an installed entry
+ */
+static void destroy_entry(entry_t *entry)
+{
+ entry->child_sa->destroy(entry->child_sa);
+ entry->peer_cfg->destroy(entry->peer_cfg);
+ free(entry);
+}
+
+/**
+ * Implementation of trap_manager_t.install
+ */
+static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
+ child_cfg_t *child)
+{
+ entry_t *entry;
+ ike_cfg_t *ike_cfg;
+ child_sa_t *child_sa;
+ host_t *me, *other;
+ linked_list_t *my_ts, *other_ts;
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ status_t status;
+ u_int32_t reqid;
+
+ /* check if not already done */
+ this->lock->read_lock(this->lock);
+ enumerator = this->traps->create_enumerator(this->traps);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (streq(entry->child_sa->get_name(entry->child_sa),
+ child->get_name(child)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ if (found)
+ {
+ DBG1(DBG_CFG, "CHILD_SA named '%s' already routed",
+ child->get_name(child));
+ return 0;
+ }
+
+ /* try to resolve addresses */
+ ike_cfg = peer->get_ike_cfg(peer);
+ other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg),
+ 0, ike_cfg->get_other_port(ike_cfg));
+ if (!other)
+ {
+ DBG1(DBG_CFG, "installing trap failed, remote address unknown");
+ return 0;
+ }
+ me = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg),
+ other->get_family(other), ike_cfg->get_my_port(ike_cfg));
+ if (!me || me->is_anyaddr(me))
+ {
+ DESTROY_IF(me);
+ me = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, other, NULL);
+ if (!me)
+ {
+ DBG1(DBG_CFG, "installing trap failed, local address unknown");
+ other->destroy(other);
+ return 0;
+ }
+ me->set_port(me, ike_cfg->get_my_port(ike_cfg));
+ }
+
+ /* create and route CHILD_SA */
+ child_sa = child_sa_create(me, other, child, 0, FALSE);
+ my_ts = child->get_traffic_selectors(child, TRUE, NULL, me);
+ other_ts = child->get_traffic_selectors(child, FALSE, NULL, other);
+ me->destroy(me);
+ other->destroy(other);
+
+ /* while we don't know the finally negotiated protocol (ESP|AH), we
+ * could iterate all proposals for a best guest (TODO). But as we
+ * support ESP only for now, we set here. */
+ child_sa->set_protocol(child_sa, PROTO_ESP);
+ child_sa->set_mode(child_sa, child->get_mode(child));
+ status = child_sa->add_policies(child_sa, my_ts, other_ts);
+ my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
+ if (status != SUCCESS)
+ {
+ child_sa->destroy(child_sa);
+ DBG1(DBG_CFG, "installing trap failed");
+ return 0;
+ }
+
+ reqid = child_sa->get_reqid(child_sa);
+ entry = malloc_thing(entry_t);
+ entry->child_sa = child_sa;
+ entry->peer_cfg = peer->get_ref(peer);
+ entry->pending = NULL;
+
+ this->lock->write_lock(this->lock);
+ this->traps->insert_last(this->traps, entry);
+ this->lock->unlock(this->lock);
+
+ return reqid;
+}
+
+/**
+ * Implementation of trap_manager_t.uninstall
+ */
+static bool uninstall(private_trap_manager_t *this, u_int32_t reqid)
+{
+ enumerator_t *enumerator;
+ entry_t *entry, *found = NULL;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->traps->create_enumerator(this->traps);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->child_sa->get_reqid(entry->child_sa) == reqid)
+ {
+ this->traps->remove_at(this->traps, enumerator);
+ found = entry;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, "trap %d not found to uninstall", reqid);
+ return FALSE;
+ }
+
+ destroy_entry(found);
+ return TRUE;
+}
+
+/**
+ * convert enumerated entries to peer_cfg, child_sa
+ */
+static bool trap_filter(rwlock_t *lock, entry_t **entry, peer_cfg_t **peer_cfg,
+ void *none, child_sa_t **child_sa)
+{
+ if (peer_cfg)
+ {
+ *peer_cfg = (*entry)->peer_cfg;
+ }
+ if (child_sa)
+ {
+ *child_sa = (*entry)->child_sa;
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of trap_manager_t.create_enumerator
+ */
+static enumerator_t* create_enumerator(private_trap_manager_t *this)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->traps->create_enumerator(this->traps),
+ (void*)trap_filter, this->lock,
+ (void*)this->lock->unlock);
+}
+
+/**
+ * Implementation of trap_manager_t.acquire
+ */
+static void acquire(private_trap_manager_t *this, u_int32_t reqid,
+ traffic_selector_t *src, traffic_selector_t *dst)
+{
+ enumerator_t *enumerator;
+ entry_t *entry, *found = NULL;
+ peer_cfg_t *peer;
+ child_cfg_t *child;
+ ike_sa_t *ike_sa;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->traps->create_enumerator(this->traps);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->child_sa->get_reqid(entry->child_sa) == reqid)
+ {
+ found = entry;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d",reqid);
+ }
+ else if (found->pending)
+ {
+ DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
+ }
+ else
+ {
+ child = found->child_sa->get_config(found->child_sa);
+ peer = found->peer_cfg;
+ ike_sa = charon->ike_sa_manager->checkout_by_config(
+ charon->ike_sa_manager, peer);
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer);
+ }
+ child->get_ref(child);
+ reqid = found->child_sa->get_reqid(found->child_sa);
+ if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
+ {
+ found->pending = ike_sa;
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ }
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Complete the acquire, if successful or failed
+ */
+static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->traps->create_enumerator(this->traps);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->pending != ike_sa)
+ {
+ continue;
+ }
+ if (child_sa && child_sa->get_reqid(child_sa) !=
+ entry->child_sa->get_reqid(entry->child_sa))
+ {
+ continue;
+ }
+ entry->pending = NULL;
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ switch (state)
+ {
+ case IKE_DESTROYING:
+ complete(listener->traps, ike_sa, NULL);
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ switch (state)
+ {
+ case CHILD_INSTALLED:
+ case CHILD_DESTROYING:
+ complete(listener->traps, ike_sa, child_sa);
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+/**
+ * Implementation of trap_manager_t.destroy.
+ */
+static void destroy(private_trap_manager_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener.listener);
+ this->traps->invoke_function(this->traps, (void*)destroy_entry);
+ this->traps->destroy(this->traps);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * See header
+ */
+trap_manager_t *trap_manager_create()
+{
+ private_trap_manager_t *this = malloc_thing(private_trap_manager_t);
+
+ this->public.install = (u_int(*)(trap_manager_t*, peer_cfg_t *peer, child_cfg_t *child))install;
+ this->public.uninstall = (bool(*)(trap_manager_t*, u_int32_t id))uninstall;
+ this->public.create_enumerator = (enumerator_t*(*)(trap_manager_t*))create_enumerator;
+ this->public.acquire = (void(*)(trap_manager_t*, u_int32_t reqid, traffic_selector_t *src, traffic_selector_t *dst))acquire;
+ this->public.destroy = (void(*)(trap_manager_t*))destroy;
+
+ this->traps = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ /* register listener for IKE state changes */
+ this->listener.traps = this;
+ memset(&this->listener.listener, 0, sizeof(listener_t));
+ this->listener.listener.ike_state_change = (void*)ike_state_change;
+ this->listener.listener.child_state_change = (void*)child_state_change;
+ charon->bus->add_listener(charon->bus, &this->listener.listener);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/trap_manager.h b/src/libcharon/sa/trap_manager.h
new file mode 100644
index 000000000..37b42e2b0
--- /dev/null
+++ b/src/libcharon/sa/trap_manager.h
@@ -0,0 +1,81 @@
+/*
+ * 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 trap_manager trap_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef TRAP_MANAGER_H_
+#define TRAP_MANAGER_H_
+
+#include <library.h>
+#include <utils/enumerator.h>
+#include <config/peer_cfg.h>
+
+typedef struct trap_manager_t trap_manager_t;
+
+/**
+ * Manage policies to create SAs from traffic.
+ */
+struct trap_manager_t {
+
+ /**
+ * Install a policy as a trap.
+ *
+ * @param peer peer configuration to initiate on trap
+ * @param child child configuration to install as a trap
+ * @return reqid of installed CHILD_SA, 0 if failed
+ */
+ u_int32_t (*install)(trap_manager_t *this, peer_cfg_t *peer,
+ child_cfg_t *child);
+
+ /**
+ * Uninstall a trap policy.
+ *
+ * @param id reqid of CHILD_SA to uninstall, returned by install()
+ * @return TRUE if uninstalled successfully
+ */
+ bool (*uninstall)(trap_manager_t *this, u_int32_t reqid);
+
+ /**
+ * Create an enumerator over all installed traps.
+ *
+ * @return enumerator over (peer_cfg_t, child_sa_t)
+ */
+ enumerator_t* (*create_enumerator)(trap_manager_t *this);
+
+ /**
+ * Acquire an SA triggered by an installed trap.
+ *
+ * @param reqid requid of the triggering CHILD_SA
+ * @param src source of the triggering packet
+ * @param dst destination of the triggering packet
+ */
+ void (*acquire)(trap_manager_t *this, u_int32_t reqid,
+ traffic_selector_t *src, traffic_selector_t *dst);
+
+ /**
+ * Destroy a trap_manager_t.
+ */
+ void (*destroy)(trap_manager_t *this);
+};
+
+/**
+ * Create a trap_manager instance.
+ */
+trap_manager_t *trap_manager_create();
+
+#endif /** TRAP_MANAGER_H_ @}*/
diff --git a/src/libfast/Makefile.am b/src/libfast/Makefile.am
index 870dcd6f1..5a1193658 100644
--- a/src/libfast/Makefile.am
+++ b/src/libfast/Makefile.am
@@ -1,7 +1,7 @@
lib_LTLIBRARIES = libfast.la
libfast_la_SOURCES = context.h dispatcher.c request.h session.h \
- controller.h dispatcher.h request.c session.c filter.h
+ controller.h dispatcher.h request.c session.c filter.h smtp.c smtp.h
libfast_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lfcgi -lneo_cgi -lneo_cs -lneo_utl -lz $(PTHREADLIB)
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I/usr/include/ClearSilver
diff --git a/src/libfast/Makefile.in b/src/libfast/Makefile.in
index e5ed4a289..f6d1f20a5 100644
--- a/src/libfast/Makefile.in
+++ b/src/libfast/Makefile.in
@@ -77,7 +77,7 @@ am__DEPENDENCIES_1 =
libfast_la_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(am__DEPENDENCIES_1)
-am_libfast_la_OBJECTS = dispatcher.lo request.lo session.lo
+am_libfast_la_OBJECTS = dispatcher.lo request.lo session.lo smtp.lo
libfast_la_OBJECTS = $(am_libfast_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -217,6 +217,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,7 +254,7 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
lib_LTLIBRARIES = libfast.la
libfast_la_SOURCES = context.h dispatcher.c request.h session.h \
- controller.h dispatcher.h request.c session.c filter.h
+ controller.h dispatcher.h request.c session.c filter.h smtp.c smtp.h
libfast_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lfcgi -lneo_cgi -lneo_cs -lneo_utl -lz $(PTHREADLIB)
@@ -337,6 +338,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dispatcher.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/request.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smtp.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libfast/request.c b/src/libfast/request.c
index 3f4894c45..6bf596fd8 100644
--- a/src/libfast/request.c
+++ b/src/libfast/request.c
@@ -204,14 +204,20 @@ static char* get_query_data(private_request_t *this, char *name)
}
/**
+ * Implementation of request_t.get_base.
+ */
+static char* get_base(private_request_t *this)
+{
+ return FCGX_GetParam("SCRIPT_NAME", this->req.envp);
+}
+
+/**
* Implementation of request_t.add_cookie.
*/
static void add_cookie(private_request_t *this, char *name, char *value)
{
thread_this->set(thread_this, this);
- cgi_cookie_set (this->cgi, name, value,
- FCGX_GetParam("SCRIPT_NAME", this->req.envp),
- NULL, NULL, 0, 0);
+ cgi_cookie_set (this->cgi, name, value, get_base(this), NULL, NULL, 0, 0);
}
/**
@@ -222,8 +228,7 @@ static void redirect(private_request_t *this, char *fmt, ...)
va_list args;
FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
- FCGX_FPrintF(this->req.out, "Location: %s%s",
- FCGX_GetParam("SCRIPT_NAME", this->req.envp),
+ FCGX_FPrintF(this->req.out, "Location: %s%s", get_base(this),
*fmt == '/' ? "" : "/");
va_start(args, fmt);
FCGX_VFPrintF(this->req.out, fmt, args);
@@ -232,21 +237,30 @@ static void redirect(private_request_t *this, char *fmt, ...)
}
/**
- * Implementation of request_t.to_referer.
+ * Implementation of request_t.get_referer.
*/
-static void to_referer(private_request_t *this)
+static char* get_referer(private_request_t *this)
{
- FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
- FCGX_FPrintF(this->req.out, "Location: %s\n\n",
- FCGX_GetParam("HTTP_REFERER", this->req.envp));
+ return FCGX_GetParam("HTTP_REFERER", this->req.envp);
}
/**
- * Implementation of request_t.get_base.
+ * Implementation of request_t.to_referer.
*/
-static char* get_base(private_request_t *this)
+static void to_referer(private_request_t *this)
{
- return FCGX_GetParam("SCRIPT_NAME", this->req.envp);
+ char *referer;
+
+ referer = get_referer(this);
+ if (referer)
+ {
+ FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
+ FCGX_FPrintF(this->req.out, "Location: %s\n\n", referer);
+ }
+ else
+ {
+ redirect(this, "/");
+ }
}
/**
@@ -396,6 +410,7 @@ request_t *request_create(int fd, bool debug)
this->public.session_closed = (bool(*)(request_t*))session_closed;
this->public.close_session = (void(*)(request_t*))close_session;
this->public.redirect = (void(*)(request_t*, char *fmt,...))redirect;
+ this->public.get_referer = (char*(*)(request_t*))get_referer;
this->public.to_referer = (void(*)(request_t*))to_referer;
this->public.render = (void(*)(request_t*,char*))render;
this->public.streamf = (int(*)(request_t*, char *format, ...))streamf;
diff --git a/src/libfast/request.h b/src/libfast/request.h
index 61e2d59f0..af0f8e4f5 100644
--- a/src/libfast/request.h
+++ b/src/libfast/request.h
@@ -106,7 +106,14 @@ struct request_t {
void (*redirect)(request_t *this, char *fmt, ...);
/**
- * Redirect the client to the referer.
+ * Get the HTTP referer.
+ *
+ * @return HTTP referer
+ */
+ char* (*get_referer)(request_t *this);
+
+ /**
+ * Redirect back to the referer.
*/
void (*to_referer)(request_t *this);
diff --git a/src/libfast/session.c b/src/libfast/session.c
index f03b75542..7c4548ee5 100644
--- a/src/libfast/session.c
+++ b/src/libfast/session.c
@@ -177,7 +177,9 @@ static void process(private_session_t *this, request_t *request)
if (this->controllers->get_first(this->controllers,
(void**)&current) == SUCCESS)
{
- request->redirect(request, current->get_name(current));
+ request->streamf(request,
+ "Status: 301 Moved permanently\nLocation: %s/%s\n\n",
+ request->get_base(request), current->get_name(current));
}
}
}
diff --git a/src/libfast/smtp.c b/src/libfast/smtp.c
new file mode 100644
index 000000000..4118c74a6
--- /dev/null
+++ b/src/libfast/smtp.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "smtp.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <debug.h>
+
+typedef struct private_smtp_t private_smtp_t;
+
+/**
+ * Private data of an smtp_t object.
+ */
+struct private_smtp_t {
+
+ /**
+ * Public smtp_t interface.
+ */
+ smtp_t public;
+
+ /**
+ * file stream to SMTP server
+ */
+ FILE *f;
+};
+
+/**
+ * Read the response code from an SMTP server
+ */
+static int read_response(private_smtp_t *this)
+{
+ char buf[256], *end;
+ int res = 0;
+
+ while (TRUE)
+ {
+ if (!fgets(buf, sizeof(buf), this->f))
+ {
+ return 0;
+ }
+ res = strtol(buf, &end, 10);
+ switch (*end)
+ {
+ case '-':
+ continue;
+ case ' ':
+ case '\0':
+ case '\n':
+ break;
+ default:
+ return 0;
+ }
+ break;
+ }
+ return res;
+}
+
+/**
+ * write a SMTP command to the server, read response code
+ */
+static int write_cmd(private_smtp_t *this, char *fmt, ...)
+{
+ char buf[256];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (fprintf(this->f, "%s\n", buf) < 1)
+ {
+ DBG1(DBG_LIB, "sending SMTP command failed");
+ return 0;
+ }
+ return read_response(this);
+}
+
+METHOD(smtp_t, send_mail, bool,
+ private_smtp_t *this, char *from, char *to, char *subject, char *fmt, ...)
+{
+ va_list args;
+
+ if (write_cmd(this, "MAIL FROM:<%s>", from) != 250)
+ {
+ DBG1(DBG_LIB, "SMTP MAIL FROM failed");
+ return FALSE;
+ }
+ if (write_cmd(this, "RCPT TO:<%s>", to) != 250)
+ {
+ DBG1(DBG_LIB, "SMTP RCPT TO failed");
+ return FALSE;
+ }
+ if (write_cmd(this, "DATA") != 354)
+ {
+ DBG1(DBG_LIB, "SMTP DATA failed");
+ return FALSE;
+ }
+
+ fprintf(this->f, "From: %s\n", from);
+ fprintf(this->f, "To: %s\n", to);
+ fprintf(this->f, "Subject: %s\n", subject);
+ fprintf(this->f, "\n");
+ va_start(args, fmt);
+ vfprintf(this->f, fmt, args);
+ va_end(args);
+ fprintf(this->f, "\n.\n");
+ return read_response(this) == 250;
+}
+
+
+METHOD(smtp_t, destroy, void,
+ private_smtp_t *this)
+{
+ write_cmd(this, "QUIT");
+ fclose(this->f);
+ free(this);
+}
+
+/**
+ * See header
+ */
+smtp_t *smtp_create()
+{
+ private_smtp_t *this;
+ struct sockaddr_in addr;
+ int s;
+
+ INIT(this,
+ .public = {
+ .send_mail = _send_mail,
+ .destroy = _destroy,
+ },
+ );
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ DBG1(DBG_LIB, "opening SMTP socket failed: %s", strerror(errno));
+ free(this);
+ return NULL;
+ }
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(25);
+ if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ {
+ DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno));
+ close(s);
+ free(this);
+ return NULL;
+ }
+ this->f = fdopen(s, "a+");
+ if (!this->f)
+ {
+ DBG1(DBG_LIB, "opening stream to SMTP server failed: %s",
+ strerror(errno));
+ close(s);
+ free(this);
+ return NULL;
+ }
+ if (read_response(this) != 220 ||
+ write_cmd(this, "EHLO localhost") != 250)
+ {
+ DBG1(DBG_LIB, "SMTP EHLO failed");
+ fclose(this->f);
+ free(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/libfast/smtp.h b/src/libfast/smtp.h
new file mode 100644
index 000000000..910f18127
--- /dev/null
+++ b/src/libfast/smtp.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup smtp smtp
+ * @{ @ingroup libfast
+ */
+
+#ifndef SMTP_H_
+#define SMTP_H_
+
+typedef struct smtp_t smtp_t;
+
+#include <library.h>
+
+/**
+ * Ultra-minimalistic SMTP client. Works at most with Exim on localhost.
+ */
+struct smtp_t {
+
+ /**
+ * Send an e-mail message.
+ *
+ * @param from sender address
+ * @param to receipient address
+ * @param subject mail subject
+ * @param fmt mail body format string
+ * @param ... arguments for body format string
+ */
+ bool (*send_mail)(smtp_t *this, char *from, char *to,
+ char *subject, char *fmt, ...);
+
+ /**
+ * Destroy a smtp_t.
+ */
+ void (*destroy)(smtp_t *this);
+};
+
+/**
+ * Create a smtp instance.
+ */
+smtp_t *smtp_create();
+
+#endif /** SMTP_H_ @}*/
diff --git a/src/libfreeswan/Makefile.in b/src/libfreeswan/Makefile.in
index e72759bca..e752df82d 100644
--- a/src/libfreeswan/Makefile.in
+++ b/src/libfreeswan/Makefile.in
@@ -234,6 +234,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/libfreeswan/pfkeyv2.h b/src/libfreeswan/pfkeyv2.h
index 685db1273..725997ebc 100644
--- a/src/libfreeswan/pfkeyv2.h
+++ b/src/libfreeswan/pfkeyv2.h
@@ -337,6 +337,7 @@ struct sadb_protocol {
#define SADB_X_EALG_AES_GCM_ICV12 19
#define SADB_X_EALG_AES_GCM_ICV16 20
#define SADB_X_EALG_CAMELLIACBC 22
+#define SADB_X_EALG_NULL_AES_GMAC 23
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
diff --git a/src/libhydra/Android.mk b/src/libhydra/Android.mk
new file mode 100644
index 000000000..caad7447a
--- /dev/null
+++ b/src/libhydra/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+hydra.c hydra.h \
+attributes/attributes.c attributes/attributes.h \
+attributes/attribute_provider.h attributes/attribute_handler.h \
+attributes/attribute_manager.c attributes/attribute_manager.h \
+attributes/mem_pool.c attributes/mem_pool.h
+
+# adding the plugin source files
+
+LOCAL_SRC_FILES += $(call add_plugin, attr)
+
+# build libcharon --------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/include \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libhydra
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/src/libhydra/Makefile.am b/src/libhydra/Makefile.am
new file mode 100644
index 000000000..601a56e38
--- /dev/null
+++ b/src/libhydra/Makefile.am
@@ -0,0 +1,42 @@
+lib_LTLIBRARIES = libhydra.la
+
+libhydra_la_SOURCES = \
+hydra.c hydra.h \
+attributes/attributes.c attributes/attributes.h \
+attributes/attribute_provider.h attributes/attribute_handler.h \
+attributes/attribute_manager.c attributes/attribute_manager.h \
+attributes/mem_pool.c attributes/mem_pool.h
+
+libhydra_la_LIBADD =
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+AM_CFLAGS = \
+-DIPSEC_DIR=\"${ipsecdir}\" \
+-DPLUGINDIR=\"${plugindir}\" \
+-DSTRONGSWAN_CONF=\"${strongswan_conf}\"
+
+EXTRA_DIST = Android.mk
+
+# build optional plugins
+########################
+
+if MONOLITHIC
+SUBDIRS =
+else
+SUBDIRS = .
+endif
+
+if USE_ATTR
+ SUBDIRS += plugins/attr
+if MONOLITHIC
+ libhydra_la_LIBADD += plugins/attr/libstrongswan-attr.la
+endif
+endif
+
+if USE_ATTR_SQL
+ SUBDIRS += plugins/attr_sql
+if MONOLITHIC
+ libhydra_la_LIBADD += plugins/attr_sql/libstrongswan-attr-sql.la
+endif
+endif
+
diff --git a/src/libhydra/Makefile.in b/src/libhydra/Makefile.in
new file mode 100644
index 000000000..32027d1ea
--- /dev/null
+++ b/src/libhydra/Makefile.in
@@ -0,0 +1,762 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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@
+@USE_ATTR_TRUE@am__append_1 = plugins/attr
+@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_2 = plugins/attr/libstrongswan-attr.la
+@USE_ATTR_SQL_TRUE@am__append_3 = plugins/attr_sql
+@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_4 = plugins/attr_sql/libstrongswan-attr-sql.la
+subdir = src/libhydra
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libhydra_la_DEPENDENCIES = $(am__append_2) $(am__append_4)
+am_libhydra_la_OBJECTS = hydra.lo attributes.lo attribute_manager.lo \
+ mem_pool.lo
+libhydra_la_OBJECTS = $(am_libhydra_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libhydra_la_SOURCES)
+DIST_SOURCES = $(libhydra_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = . plugins/attr plugins/attr_sql
+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@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+lib_LTLIBRARIES = libhydra.la
+libhydra_la_SOURCES = \
+hydra.c hydra.h \
+attributes/attributes.c attributes/attributes.h \
+attributes/attribute_provider.h attributes/attribute_handler.h \
+attributes/attribute_manager.c attributes/attribute_manager.h \
+attributes/mem_pool.c attributes/mem_pool.h
+
+libhydra_la_LIBADD = $(am__append_2) $(am__append_4)
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+AM_CFLAGS = \
+-DIPSEC_DIR=\"${ipsecdir}\" \
+-DPLUGINDIR=\"${plugindir}\" \
+-DSTRONGSWAN_CONF=\"${strongswan_conf}\"
+
+EXTRA_DIST = Android.mk
+@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_1) $(am__append_3)
+
+# build optional plugins
+########################
+@MONOLITHIC_TRUE@SUBDIRS = $(am__append_1) $(am__append_3)
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libhydra/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libhydra.la: $(libhydra_la_OBJECTS) $(libhydra_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libhydra_la_OBJECTS) $(libhydra_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attribute_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attributes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hydra.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_pool.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+attributes.lo: attributes/attributes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attributes.lo -MD -MP -MF $(DEPDIR)/attributes.Tpo -c -o attributes.lo `test -f 'attributes/attributes.c' || echo '$(srcdir)/'`attributes/attributes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/attributes.Tpo $(DEPDIR)/attributes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attributes/attributes.c' object='attributes.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attributes.lo `test -f 'attributes/attributes.c' || echo '$(srcdir)/'`attributes/attributes.c
+
+attribute_manager.lo: attributes/attribute_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attribute_manager.lo -MD -MP -MF $(DEPDIR)/attribute_manager.Tpo -c -o attribute_manager.lo `test -f 'attributes/attribute_manager.c' || echo '$(srcdir)/'`attributes/attribute_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/attribute_manager.Tpo $(DEPDIR)/attribute_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attributes/attribute_manager.c' object='attribute_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attribute_manager.lo `test -f 'attributes/attribute_manager.c' || echo '$(srcdir)/'`attributes/attribute_manager.c
+
+mem_pool.lo: attributes/mem_pool.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mem_pool.lo -MD -MP -MF $(DEPDIR)/mem_pool.Tpo -c -o mem_pool.lo `test -f 'attributes/mem_pool.c' || echo '$(srcdir)/'`attributes/mem_pool.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mem_pool.Tpo $(DEPDIR)/mem_pool.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attributes/mem_pool.c' object='mem_pool.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mem_pool.lo `test -f 'attributes/mem_pool.c' || echo '$(srcdir)/'`attributes/mem_pool.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _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.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; 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"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+ 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-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-libLTLIBRARIES
+
+
+# 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/attributes/attribute_handler.h b/src/libhydra/attributes/attribute_handler.h
new file mode 100644
index 000000000..d042f47ef
--- /dev/null
+++ b/src/libhydra/attributes/attribute_handler.h
@@ -0,0 +1,72 @@
+/*
+ * 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 attribute_handler attribute_handler
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_HANDLER_H_
+#define ATTRIBUTE_HANDLER_H_
+
+#include <chunk.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+
+#include "attributes.h"
+
+typedef struct attribute_handler_t attribute_handler_t;
+
+/**
+ * Interface to handle configuration payload attributes.
+ */
+struct attribute_handler_t {
+
+ /**
+ * Handle a configuration attribute.
+ *
+ * After receiving a configuration attriubte, it is passed to each
+ * attribute handler until it is handled.
+ *
+ * @param server server from which the attribute was received
+ * @param type type of configuration attribute to handle
+ * @param data associated attribute data
+ * @return TRUE if attribute handled
+ */
+ bool (*handle)(attribute_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Release an attribute handled during handle().
+ *
+ * A handler that handle()d an attribute gets a call to release() when the
+ * connection gets closed. Depending on the implementation, this is required
+ * to remove the attribute.
+ */
+ void (*release)(attribute_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Enumerate attributes to request from a server.
+ *
+ * @param server server identity to request attributes from
+ * @param vip virtual IP we are requesting, if any
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
+ identification_t *server, host_t *vip);
+};
+
+#endif /** ATTRIBUTE_HANDLER_H_ @}*/
diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c
new file mode 100644
index 000000000..3080b56eb
--- /dev/null
+++ b/src/libhydra/attributes/attribute_manager.c
@@ -0,0 +1,374 @@
+/*
+ * 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.
+ */
+
+#include "attribute_manager.h"
+
+#include <debug.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_attribute_manager_t private_attribute_manager_t;
+
+/**
+ * private data of attribute_manager
+ */
+struct private_attribute_manager_t {
+
+ /**
+ * public functions
+ */
+ attribute_manager_t public;
+
+ /**
+ * list of registered providers
+ */
+ linked_list_t *providers;
+
+ /**
+ * list of registered handlers
+ */
+ linked_list_t *handlers;
+
+ /**
+ * rwlock provider list
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Data to pass to enumerator filters
+ */
+typedef struct {
+ /** server/peer identity */
+ identification_t *id;
+ /** requesting/assigned virtual IP */
+ host_t *vip;
+} enum_data_t;
+
+/**
+ * Implementation of attribute_manager_t.acquire_address.
+ */
+static host_t* acquire_address(private_attribute_manager_t *this,
+ char *pool, identification_t *id,
+ host_t *requested)
+{
+ enumerator_t *enumerator;
+ attribute_provider_t *current;
+ host_t *host = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ host = current->acquire_address(current, pool, id, requested);
+ if (host)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!host)
+ {
+ DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool);
+ }
+ return host;
+}
+
+/**
+ * Implementation of attribute_manager_t.release_address.
+ */
+static void release_address(private_attribute_manager_t *this,
+ char *pool, host_t *address, identification_t *id)
+{
+ enumerator_t *enumerator;
+ attribute_provider_t *current;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->release_address(current, pool, address, id))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool);
+ }
+}
+
+/**
+ * inner enumerator constructor for responder attributes
+ */
+static enumerator_t *responder_enum_create(attribute_provider_t *provider,
+ enum_data_t *data)
+{
+ return provider->create_attribute_enumerator(provider, data->id, data->vip);
+}
+
+/**
+ * Implementation of attribute_manager_t.create_responder_enumerator
+ */
+static enumerator_t* create_responder_enumerator(
+ private_attribute_manager_t *this, identification_t *id, host_t *vip)
+{
+ enum_data_t *data = malloc_thing(enum_data_t);
+
+ data->id = id;
+ data->vip = vip;
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(
+ enumerator_create_nested(
+ this->providers->create_enumerator(this->providers),
+ (void*)responder_enum_create, data, free),
+ (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * Implementation of attribute_manager_t.add_provider.
+ */
+static void add_provider(private_attribute_manager_t *this,
+ attribute_provider_t *provider)
+{
+ this->lock->write_lock(this->lock);
+ this->providers->insert_last(this->providers, provider);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of attribute_manager_t.remove_provider.
+ */
+static void remove_provider(private_attribute_manager_t *this,
+ attribute_provider_t *provider)
+{
+ this->lock->write_lock(this->lock);
+ this->providers->remove(this->providers, provider, NULL);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of attribute_manager_t.handle
+ */
+static attribute_handler_t* handle(private_attribute_manager_t *this,
+ identification_t *server, attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ enumerator_t *enumerator;
+ attribute_handler_t *current, *handled = NULL;
+
+ this->lock->read_lock(this->lock);
+
+ /* try to find the passed handler */
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == handler && current->handle(current, server, type, data))
+ {
+ handled = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!handled)
+ { /* handler requesting this attribute not found, try any other */
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->handle(current, server, type, data))
+ {
+ handled = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->lock->unlock(this->lock);
+
+ if (!handled)
+ {
+ DBG1(DBG_CFG, "handling %N attribute failed",
+ configuration_attribute_type_names, type);
+ }
+ return handled;
+}
+
+/**
+ * Implementation of attribute_manager_t.release
+ */
+static void release(private_attribute_manager_t *this,
+ attribute_handler_t *handler,
+ identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ enumerator_t *enumerator;
+ attribute_handler_t *current;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == handler)
+ {
+ current->release(current, server, type, data);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Enumerator implementation to enumerate nested initiator attributes
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** back ref */
+ private_attribute_manager_t *this;
+ /** currently processing handler */
+ attribute_handler_t *handler;
+ /** outer enumerator over handlers */
+ enumerator_t *outer;
+ /** inner enumerator over current handlers attributes */
+ enumerator_t *inner;
+ /** server ID we want attributes for */
+ identification_t *id;
+ /** virtual IP we are requesting along with attriubutes */
+ host_t *vip;
+} initiator_enumerator_t;
+
+/**
+ * Enumerator implementation for initiator attributes
+ */
+static bool initiator_enumerate(initiator_enumerator_t *this,
+ attribute_handler_t **handler,
+ configuration_attribute_type_t *type,
+ chunk_t *value)
+{
+ /* enumerate inner attributes using outer handler enumerator */
+ while (!this->inner || !this->inner->enumerate(this->inner, type, value))
+ {
+ if (!this->outer->enumerate(this->outer, &this->handler))
+ {
+ return FALSE;
+ }
+ DESTROY_IF(this->inner);
+ this->inner = this->handler->create_attribute_enumerator(this->handler,
+ this->id, this->vip);
+ }
+ /* inject the handler as additional attribute */
+ *handler = this->handler;
+ return TRUE;
+}
+
+/**
+ * Cleanup function of initiator attribute enumerator
+ */
+static void initiator_destroy(initiator_enumerator_t *this)
+{
+ this->this->lock->unlock(this->this->lock);
+ this->outer->destroy(this->outer);
+ DESTROY_IF(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of attribute_manager_t.create_initiator_enumerator
+ */
+static enumerator_t* create_initiator_enumerator(
+ private_attribute_manager_t *this, identification_t *id, host_t *vip)
+{
+ initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t);
+
+ this->lock->read_lock(this->lock);
+ enumerator->public.enumerate = (void*)initiator_enumerate;
+ enumerator->public.destroy = (void*)initiator_destroy;
+ enumerator->this = this;
+ enumerator->id = id;
+ enumerator->vip = vip;
+ enumerator->outer = this->handlers->create_enumerator(this->handlers);
+ enumerator->inner = NULL;
+ enumerator->handler = NULL;
+
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of attribute_manager_t.add_handler
+ */
+static void add_handler(private_attribute_manager_t *this,
+ attribute_handler_t *handler)
+{
+ this->lock->write_lock(this->lock);
+ this->handlers->insert_last(this->handlers, handler);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of attribute_manager_t.remove_handler
+ */
+static void remove_handler(private_attribute_manager_t *this,
+ attribute_handler_t *handler)
+{
+ this->lock->write_lock(this->lock);
+ this->handlers->remove(this->handlers, handler, NULL);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Implementation of attribute_manager_t.destroy
+ */
+static void destroy(private_attribute_manager_t *this)
+{
+ this->providers->destroy(this->providers);
+ this->handlers->destroy(this->handlers);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+attribute_manager_t *attribute_manager_create()
+{
+ private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t);
+
+ this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
+ this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
+ this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator;
+ this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
+ this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
+ this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
+ this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
+ this->public.create_initiator_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_initiator_enumerator;
+ this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))add_handler;
+ this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
+ this->public.destroy = (void(*)(attribute_manager_t*))destroy;
+
+ this->providers = linked_list_create();
+ this->handlers = linked_list_create();
+ this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+
+ return &this->public;
+}
+
diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h
new file mode 100644
index 000000000..642662366
--- /dev/null
+++ b/src/libhydra/attributes/attribute_manager.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2008-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 attribute_manager attribute_manager
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_MANAGER_H_
+#define ATTRIBUTE_MANAGER_H_
+
+#include "attribute_provider.h"
+#include "attribute_handler.h"
+
+typedef struct attribute_manager_t attribute_manager_t;
+
+/**
+ * The attribute manager hands out attributes or handles them.
+ *
+ * The attribute manager manages both, attribute providers and attribute
+ * handlers. Attribute providers are responsible to hand out attributes if
+ * a connecting peer requests them. Handlers handle such attributes if they
+ * are received on the requesting peer.
+ */
+struct attribute_manager_t {
+
+ /**
+ * Acquire a virtual IP address to assign to a peer.
+ *
+ * @param pool pool name to acquire address from
+ * @param id peer identity to get address forua
+ * @param requested IP in configuration request
+ * @return allocated address, NULL to serve none
+ */
+ host_t* (*acquire_address)(attribute_manager_t *this,
+ char *pool, identification_t *id,
+ host_t *requested);
+
+ /**
+ * Release a previously acquired address.
+ *
+ * @param pool pool name from which the address was acquired
+ * @param address address to release
+ * @param id peer identity to get address for
+ */
+ void (*release_address)(attribute_manager_t *this,
+ char *pool, host_t *address, identification_t *id);
+
+ /**
+ * Create an enumerator over attributes to hand out to a peer.
+ *
+ * @param id peer identity to hand out attributes to
+ * @param vip virtual IP to assign to peer, if any
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
+ identification_t *id, host_t *vip);
+
+ /**
+ * Register an attribute provider to the manager.
+ *
+ * @param provider attribute provider to register
+ */
+ void (*add_provider)(attribute_manager_t *this,
+ attribute_provider_t *provider);
+ /**
+ * Unregister an attribute provider from the manager.
+ *
+ * @param provider attribute provider to unregister
+ */
+ void (*remove_provider)(attribute_manager_t *this,
+ attribute_provider_t *provider);
+
+ /**
+ * Handle a configuration attribute by passing them to the handlers.
+ *
+ * @param server server from which the attribute was received
+ * @param handler handler we requested the attribute for, if any
+ * @param type type of configuration attribute
+ * @param data associated attribute data
+ * @return handler which handled this attribute, NULL if none
+ */
+ attribute_handler_t* (*handle)(attribute_manager_t *this,
+ identification_t *server, attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Release an attribute previously handle()d by a handler.
+ *
+ * @param handler handler returned by handle() for this attribute
+ * @param server server from which the attribute was received
+ * @param type type of attribute to release
+ * @param data associated attribute data
+ */
+ void (*release)(attribute_manager_t *this, attribute_handler_t *handler,
+ identification_t *server,
+ configuration_attribute_type_t type,
+ chunk_t data);
+
+ /**
+ * Create an enumerator over attributes to request from server.
+ *
+ * @param id server identity to hand out attributes to
+ * @param vip virtual IP going to request, if any
+ * @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
+ */
+ enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
+ identification_t *id, host_t *vip);
+
+ /**
+ * Register an attribute handler to the manager.
+ *
+ * @param handler attribute handler to register
+ */
+ void (*add_handler)(attribute_manager_t *this,
+ attribute_handler_t *handler);
+
+ /**
+ * Unregister an attribute handler from the manager.
+ *
+ * @param handler attribute handler to unregister
+ */
+ void (*remove_handler)(attribute_manager_t *this,
+ attribute_handler_t *handler);
+
+ /**
+ * Destroy a attribute_manager instance.
+ */
+ void (*destroy)(attribute_manager_t *this);
+};
+
+/**
+ * Create a attribute_manager instance.
+ */
+attribute_manager_t *attribute_manager_create();
+
+#endif /** ATTRIBUTE_MANAGER_H_ @}*/
diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h
new file mode 100644
index 000000000..f8485cc6c
--- /dev/null
+++ b/src/libhydra/attributes/attribute_provider.h
@@ -0,0 +1,67 @@
+/*
+ * 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 attribute_provider attribute_provider
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_PROVIDER_H_
+#define ATTRIBUTE_PROVIDER_H_
+
+#include <utils/host.h>
+#include <utils/identification.h>
+
+typedef struct attribute_provider_t attribute_provider_t;
+
+/**
+ * Interface to provide attributes to peers through attribute manager.
+ */
+struct attribute_provider_t {
+
+ /**
+ * Acquire a virtual IP address to assign to a peer.
+ *
+ * @param pool name of the pool to acquire address from
+ * @param id peer ID
+ * @param requested IP in configuration request
+ * @return allocated address, NULL to serve none
+ */
+ host_t* (*acquire_address)(attribute_provider_t *this,
+ char *pool, identification_t *id,
+ host_t *requested);
+ /**
+ * Release a previously acquired address.
+ *
+ * @param pool name of the pool this address was acquired from
+ * @param address address to release
+ * @param id peer ID
+ * @return TRUE if the address has been released by the provider
+ */
+ bool (*release_address)(attribute_provider_t *this,
+ char *pool, host_t *address, identification_t *id);
+
+ /**
+ * Create an enumerator over attributes to hand out to a peer.
+ *
+ * @param id peer ID
+ * @param vip virtual IP to assign to peer, if any
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
+ identification_t *id, host_t *vip);
+};
+
+#endif /** ATTRIBUTE_PROVIDER_H_ @}*/
diff --git a/src/libhydra/attributes/attributes.c b/src/libhydra/attributes/attributes.c
new file mode 100644
index 000000000..83feed17e
--- /dev/null
+++ b/src/libhydra/attributes/attributes.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "attributes.h"
+
+ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, INTERNAL_IP6_PREFIX,
+ "INTERNAL_IP4_ADDRESS",
+ "INTERNAL_IP4_NETMASK",
+ "INTERNAL_IP4_DNS",
+ "INTERNAL_IP4_NBNS",
+ "INTERNAL_ADDRESS_EXPIRY",
+ "INTERNAL_IP4_DHCP",
+ "APPLICATION_VERSION",
+ "INTERNAL_IP6_ADDRESS",
+ "INTERNAL_IP6_NETMASK",
+ "INTERNAL_IP6_DNS",
+ "INTERNAL_IP6_NBNS",
+ "INTERNAL_IP6_DHCP",
+ "INTERNAL_IP4_SUBNET",
+ "SUPPORTED_ATTRIBUTES",
+ "INTERNAL_IP6_SUBNET",
+ "MIP6_HOME_PREFIX",
+ "INTERNAL_IP6_LINK",
+ "INTERNAL_IP6_PREFIX");
+ENUM_NEXT(configuration_attribute_type_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, INTERNAL_IP6_PREFIX,
+ "INTERNAL_IP4_SERVER",
+ "INTERNAL_IP6_SERVER");
+ENUM_END(configuration_attribute_type_names, INTERNAL_IP6_SERVER);
+
diff --git a/src/libhydra/attributes/attributes.h b/src/libhydra/attributes/attributes.h
new file mode 100644
index 000000000..f4a396f21
--- /dev/null
+++ b/src/libhydra/attributes/attributes.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup attributes_g attributes
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTES_H_
+#define ATTRIBUTES_H_
+
+typedef enum configuration_attribute_type_t configuration_attribute_type_t;
+
+#include <enum.h>
+
+/**
+ * Type of the attribute, as in IKEv2 RFC 3.15.1 or IKEv1 ModeConfig.
+ */
+enum configuration_attribute_type_t {
+ INTERNAL_IP4_ADDRESS = 1,
+ INTERNAL_IP4_NETMASK = 2,
+ INTERNAL_IP4_DNS = 3,
+ INTERNAL_IP4_NBNS = 4,
+ INTERNAL_ADDRESS_EXPIRY = 5,
+ INTERNAL_IP4_DHCP = 6,
+ APPLICATION_VERSION = 7,
+ INTERNAL_IP6_ADDRESS = 8,
+ INTERNAL_IP6_NETMASK = 9,
+ INTERNAL_IP6_DNS = 10,
+ INTERNAL_IP6_NBNS = 11,
+ INTERNAL_IP6_DHCP = 12,
+ INTERNAL_IP4_SUBNET = 13,
+ SUPPORTED_ATTRIBUTES = 14,
+ INTERNAL_IP6_SUBNET = 15,
+ MIP6_HOME_PREFIX = 16,
+ INTERNAL_IP6_LINK = 17,
+ INTERNAL_IP6_PREFIX = 18,
+ /* proprietary Microsoft attributes */
+ INTERNAL_IP4_SERVER = 23456,
+ INTERNAL_IP6_SERVER = 23457
+};
+
+/**
+ * enum names for configuration_attribute_type_t.
+ */
+extern enum_name_t *configuration_attribute_type_names;
+
+
+#endif /** ATTRIBUTES_H_ @}*/
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
new file mode 100644
index 000000000..65018e3a9
--- /dev/null
+++ b/src/libhydra/attributes/mem_pool.c
@@ -0,0 +1,451 @@
+/*
+ * 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.
+ */
+
+#include "mem_pool.h"
+
+#include <debug.h>
+#include <utils/hashtable.h>
+#include <threading/rwlock.h>
+
+#define POOL_LIMIT (sizeof(uintptr_t)*8)
+
+typedef struct private_mem_pool_t private_mem_pool_t;
+
+/**
+ * private data of mem_pool_t
+ */
+struct private_mem_pool_t {
+ /**
+ * public interface
+ */
+ mem_pool_t public;
+
+ /**
+ * name of the pool
+ */
+ char *name;
+
+ /**
+ * base address of the pool
+ */
+ host_t *base;
+
+ /**
+ * size of the pool
+ */
+ u_int size;
+
+ /**
+ * next unused address
+ */
+ u_int unused;
+
+ /**
+ * hashtable [identity => offset], for online leases
+ */
+ hashtable_t *online;
+
+ /**
+ * hashtable [identity => offset], for offline leases
+ */
+ hashtable_t *offline;
+
+ /**
+ * hashtable [identity => identity], handles identity references
+ */
+ hashtable_t *ids;
+
+ /**
+ * lock to safely access the pool
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * hashtable hash function for identities
+ */
+static u_int id_hash(identification_t *id)
+{
+ return chunk_hash(id->get_encoding(id));
+}
+
+/**
+ * hashtable equals function for identities
+ */
+static bool id_equals(identification_t *a, identification_t *b)
+{
+ return a->equals(a, b);
+}
+
+/**
+ * convert a pool offset to an address
+ */
+static host_t* offset2host(private_mem_pool_t *pool, int offset)
+{
+ chunk_t addr;
+ host_t *host;
+ u_int32_t *pos;
+
+ offset--;
+ if (offset > pool->size)
+ {
+ return NULL;
+ }
+
+ addr = chunk_clone(pool->base->get_address(pool->base));
+ if (pool->base->get_family(pool->base) == AF_INET6)
+ {
+ pos = (u_int32_t*)(addr.ptr + 12);
+ }
+ else
+ {
+ pos = (u_int32_t*)addr.ptr;
+ }
+ *pos = htonl(offset + ntohl(*pos));
+ host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0);
+ free(addr.ptr);
+ return host;
+}
+
+/**
+ * convert a host to a pool offset
+ */
+static int host2offset(private_mem_pool_t *pool, host_t *addr)
+{
+ chunk_t host, base;
+ u_int32_t hosti, basei;
+
+ if (addr->get_family(addr) != pool->base->get_family(pool->base))
+ {
+ return -1;
+ }
+ host = addr->get_address(addr);
+ base = pool->base->get_address(pool->base);
+ if (addr->get_family(addr) == AF_INET6)
+ {
+ /* only look at last /32 block */
+ if (!memeq(host.ptr, base.ptr, 12))
+ {
+ return -1;
+ }
+ host = chunk_skip(host, 12);
+ base = chunk_skip(base, 12);
+ }
+ hosti = ntohl(*(u_int32_t*)(host.ptr));
+ basei = ntohl(*(u_int32_t*)(base.ptr));
+ if (hosti > basei + pool->size)
+ {
+ return -1;
+ }
+ return hosti - basei + 1;
+}
+
+METHOD(mem_pool_t, get_name, const char*,
+ private_mem_pool_t *this)
+{
+ return this->name;
+}
+
+METHOD(mem_pool_t, get_size, u_int,
+ private_mem_pool_t *this)
+{
+ return this->size;
+}
+
+METHOD(mem_pool_t, get_online, u_int,
+ private_mem_pool_t *this)
+{
+ u_int count;
+ this->lock->read_lock(this->lock);
+ count = this->online->get_count(this->online);
+ this->lock->unlock(this->lock);
+ return count;
+}
+
+METHOD(mem_pool_t, get_offline, u_int,
+ private_mem_pool_t *this)
+{
+ u_int count;
+ this->lock->read_lock(this->lock);
+ count = this->offline->get_count(this->offline);
+ this->lock->unlock(this->lock);
+ return count;
+}
+
+METHOD(mem_pool_t, acquire_address, host_t*,
+ private_mem_pool_t *this, identification_t *id, host_t *requested)
+{
+ uintptr_t offset = 0;
+ enumerator_t *enumerator;
+ identification_t *old_id;
+
+ /* if the pool is empty (e.g. in the %config case) we simply return the
+ * requested address */
+ if (this->size == 0)
+ {
+ return requested->clone(requested);
+ }
+
+ if (!requested->is_anyaddr(requested) &&
+ requested->get_family(requested) !=
+ this->base->get_family(this->base))
+ {
+ DBG1(DBG_CFG, "IP pool address family mismatch");
+ return NULL;
+ }
+
+ this->lock->write_lock(this->lock);
+ while (TRUE)
+ {
+ /* check for a valid offline lease, refresh */
+ offset = (uintptr_t)this->offline->remove(this->offline, id);
+ if (offset)
+ {
+ id = this->ids->get(this->ids, id);
+ if (id)
+ {
+ DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
+ this->online->put(this->online, id, (void*)offset);
+ break;
+ }
+ }
+
+ /* check for a valid online lease, reassign */
+ offset = (uintptr_t)this->online->get(this->online, id);
+ if (offset && offset == host2offset(this, requested))
+ {
+ DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
+ break;
+ }
+
+ if (this->unused < this->size)
+ {
+ /* assigning offset, starting by 1. Handling 0 in hashtable
+ * is difficult. */
+ offset = ++this->unused;
+ id = id->clone(id);
+ this->ids->put(this->ids, id, id);
+ this->online->put(this->online, id, (void*)offset);
+ DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ break;
+ }
+
+ /* no more addresses, replace the first found offline lease */
+ enumerator = this->offline->create_enumerator(this->offline);
+ if (enumerator->enumerate(enumerator, &old_id, &offset))
+ {
+ offset = (uintptr_t)this->offline->remove(this->offline, old_id);
+ if (offset)
+ {
+ /* destroy reference to old ID */
+ old_id = this->ids->remove(this->ids, old_id);
+ DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
+ " to '%Y'", old_id, id);
+ if (old_id)
+ {
+ old_id->destroy(old_id);
+ }
+ id = id->clone(id);
+ this->ids->put(this->ids, id, id);
+ this->online->put(this->online, id, (void*)offset);
+ enumerator->destroy(enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
+ this->name);
+ break;
+ }
+ this->lock->unlock(this->lock);
+
+ if (offset)
+ {
+ return offset2host(this, offset);
+ }
+ return NULL;
+}
+
+METHOD(mem_pool_t, release_address, bool,
+ private_mem_pool_t *this, host_t *address, identification_t *id)
+{
+ bool found = FALSE;
+ if (this->size != 0)
+ {
+ uintptr_t offset;
+ this->lock->write_lock(this->lock);
+ offset = (uintptr_t)this->online->remove(this->online, id);
+ if (offset)
+ {
+ id = this->ids->get(this->ids, id);
+ if (id)
+ {
+ DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
+ this->offline->put(this->offline, id, (void*)offset);
+ found = TRUE;
+ }
+ }
+ this->lock->unlock(this->lock);
+ }
+ return found;
+}
+
+/**
+ * lease enumerator
+ */
+typedef struct {
+ /** implemented enumerator interface */
+ enumerator_t public;
+ /** inner hash-table enumerator */
+ enumerator_t *inner;
+ /** enumerated pool */
+ private_mem_pool_t *pool;
+ /** currently enumerated lease address */
+ host_t *current;
+} lease_enumerator_t;
+
+METHOD(enumerator_t, lease_enumerate, bool,
+ lease_enumerator_t *this, identification_t **id_out, host_t **addr_out,
+ bool *online)
+{
+ identification_t *id;
+ uintptr_t offset;
+
+ DESTROY_IF(this->current);
+ this->current = NULL;
+
+ if (this->inner->enumerate(this->inner, &id, NULL))
+ {
+ offset = (uintptr_t)this->pool->online->get(this->pool->online, id);
+ if (offset)
+ {
+ *id_out = id;
+ *addr_out = this->current = offset2host(this->pool, offset);
+ *online = TRUE;
+ return TRUE;
+ }
+ offset = (uintptr_t)this->pool->offline->get(this->pool->offline, id);
+ if (offset)
+ {
+ *id_out = id;
+ *addr_out = this->current = offset2host(this->pool, offset);
+ *online = FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(enumerator_t, lease_enumerator_destroy, void,
+ lease_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ this->pool->lock->unlock(this->pool->lock);
+ free(this);
+}
+
+METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
+ private_mem_pool_t *this)
+{
+ lease_enumerator_t *enumerator;
+ this->lock->read_lock(this->lock);
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_lease_enumerate,
+ .destroy = (void*)_lease_enumerator_destroy,
+ },
+ .pool = this,
+ .inner = this->ids->create_enumerator(this->ids),
+ );
+ return &enumerator->public;
+}
+
+METHOD(mem_pool_t, destroy, void,
+ private_mem_pool_t *this)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+
+ enumerator = this->ids->create_enumerator(this->ids);
+ while (enumerator->enumerate(enumerator, &id, NULL))
+ {
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ this->ids->destroy(this->ids);
+ this->online->destroy(this->online);
+ this->offline->destroy(this->offline);
+ this->lock->destroy(this->lock);
+ DESTROY_IF(this->base);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Described in header
+ */
+mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
+{
+ private_mem_pool_t *this;
+
+ INIT(this,
+ .public = {
+ .get_name = _get_name,
+ .get_size = _get_size,
+ .get_online = _get_online,
+ .get_offline = _get_offline,
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_lease_enumerator = _create_lease_enumerator,
+ .destroy = _destroy,
+ },
+ .name = strdup(name),
+ .online = hashtable_create((hashtable_hash_t)id_hash,
+ (hashtable_equals_t)id_equals, 16),
+ .offline = hashtable_create((hashtable_hash_t)id_hash,
+ (hashtable_equals_t)id_equals, 16),
+ .ids = hashtable_create((hashtable_hash_t)id_hash,
+ (hashtable_equals_t)id_equals, 16),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ if (base)
+ {
+ int addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
+ /* net bits -> host bits */
+ bits = addr_bits - bits;
+ if (bits > POOL_LIMIT)
+ {
+ bits = POOL_LIMIT;
+ DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
+ base, addr_bits - bits);
+ }
+ this->size = 1 << (bits);
+
+ if (this->size > 2)
+ { /* do not use first and last addresses of a block */
+ this->unused++;
+ this->size--;
+ }
+ this->base = base->clone(base);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h
new file mode 100644
index 000000000..bb963de93
--- /dev/null
+++ b/src/libhydra/attributes/mem_pool.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup mem_pool mem_pool
+ * @{ @ingroup attributes
+ */
+
+#ifndef MEM_POOL_H
+#define MEM_POOL_H
+
+typedef struct mem_pool_t mem_pool_t;
+
+#include <utils/host.h>
+#include <utils/identification.h>
+
+/**
+ * An in-memory IP address pool.
+ */
+struct mem_pool_t {
+
+ /**
+ * Get the name of this pool.
+ *
+ * @return the name of this pool
+ */
+ const char* (*get_name)(mem_pool_t *this);
+
+ /**
+ * Get the size (i.e. number of addresses) of this pool.
+ *
+ * @return the size of this pool
+ */
+ u_int (*get_size)(mem_pool_t *this);
+
+ /**
+ * Get the number of online leases.
+ *
+ * @return the number of offline leases
+ */
+ u_int (*get_online)(mem_pool_t *this);
+
+ /**
+ * Get the number of offline leases.
+ *
+ * @return the number of online leases
+ */
+ u_int (*get_offline)(mem_pool_t *this);
+
+ /**
+ * Acquire an address for the given id from this pool.
+ *
+ * @param id the id to acquire an address for
+ * @param requested acquire this address, if possible
+ * @return the acquired address
+ */
+ host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
+ host_t *requested);
+
+ /**
+ * Release a previously acquired address.
+ *
+ * @param address the address to release
+ * @param id the id the address was assigned to
+ * @return TRUE, if the lease was found
+ */
+ bool (*release_address)(mem_pool_t *this, host_t *address,
+ identification_t *id);
+
+ /**
+ * Create an enumerator over the leases of this pool.
+ *
+ * Enumerator enumerates over
+ * identification_t *id, host_t *address, bool online
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_lease_enumerator)(mem_pool_t *this);
+
+ /**
+ * Destroy a mem_pool_t instance.
+ */
+ void (*destroy)(mem_pool_t *this);
+};
+
+/**
+ * Create an in-memory IP address pool.
+ *
+ * An empty pool just returns the requested address.
+ *
+ * @param name name of this pool
+ * @param base base address of this pool, NULL to create an empty pool
+ * @param bits net mask
+ */
+mem_pool_t *mem_pool_create(char *name, host_t *base, int bits);
+
+#endif /** MEM_POOL_H_ @} */
+
diff --git a/src/libhydra/hydra.c b/src/libhydra/hydra.c
new file mode 100644
index 000000000..16a8193ea
--- /dev/null
+++ b/src/libhydra/hydra.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "hydra.h"
+
+#include <debug.h>
+
+typedef struct private_hydra_t private_hydra_t;
+
+/**
+ * Private additions to hydra_t.
+ */
+struct private_hydra_t {
+
+ /**
+ * Public members of hydra_t.
+ */
+ hydra_t public;
+};
+
+/**
+ * Single instance of hydra_t.
+ */
+hydra_t *hydra;
+
+/**
+ * Described in header.
+ */
+void libhydra_deinit()
+{
+ private_hydra_t *this = (private_hydra_t*)hydra;
+ this->public.attributes->destroy(this->public.attributes);
+ free((void*)this->public.daemon);
+ free(this);
+ hydra = NULL;
+}
+
+/**
+ * Described in header.
+ */
+bool libhydra_init(const char *daemon)
+{
+ private_hydra_t *this;
+
+ INIT(this,
+ .public = {
+ .attributes = attribute_manager_create(),
+ .daemon = strdup(daemon ?: "libhydra"),
+ },
+ );
+ hydra = &this->public;
+
+ if (lib->integrity &&
+ !lib->integrity->check(lib->integrity, "libhydra", libhydra_init))
+ {
+ DBG1(DBG_LIB, "integrity check of libhydra failed");
+ return FALSE;
+ }
+ return TRUE;
+}
+
diff --git a/src/libhydra/hydra.h b/src/libhydra/hydra.h
new file mode 100644
index 000000000..8670f3969
--- /dev/null
+++ b/src/libhydra/hydra.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup libhydra libhydra
+ *
+ * @defgroup attributes attributes
+ * @ingroup libhydra
+ *
+ * @defgroup hplugins plugins
+ * @ingroup libhydra
+ *
+ * @addtogroup libhydra
+ * @{
+ */
+
+#ifndef HYDRA_H_
+#define HYDRA_H_
+
+typedef struct hydra_t hydra_t;
+
+#include <attributes/attribute_manager.h>
+
+#include <library.h>
+
+/**
+ * IKE Daemon support object.
+ */
+struct hydra_t {
+
+ /**
+ * manager for payload attributes
+ */
+ attribute_manager_t *attributes;
+
+ /**
+ * name of the daemon that initialized the library
+ */
+ const char *daemon;
+};
+
+/**
+ * The single instance of hydra_t.
+ *
+ * Set between calls to libhydra_init() and libhydra_deinit() calls.
+ */
+extern hydra_t *hydra;
+
+/**
+ * Initialize libhydra.
+ *
+ * The daemon's name is used to load daemon-specific settings.
+ *
+ * @param daemon name of the daemon that initializes the library
+ * @return FALSE if integrity check failed
+ */
+bool libhydra_init(const char *daemon);
+
+/**
+ * Deinitialize libhydra.
+ */
+void libhydra_deinit();
+
+#endif /** HYDRA_H_ @}*/
diff --git a/src/libhydra/plugins/attr/Makefile.am b/src/libhydra/plugins/attr/Makefile.am
new file mode 100644
index 000000000..71401648e
--- /dev/null
+++ b/src/libhydra/plugins/attr/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-attr.la
+else
+plugin_LTLIBRARIES = libstrongswan-attr.la
+endif
+
+libstrongswan_attr_la_SOURCES = \
+ attr_plugin.h attr_plugin.c \
+ attr_provider.h attr_provider.c
+
+libstrongswan_attr_la_LDFLAGS = -module -avoid-version
diff --git a/src/libhydra/plugins/attr/Makefile.in b/src/libhydra/plugins/attr/Makefile.in
new file mode 100644
index 000000000..54aa64beb
--- /dev/null
+++ b/src/libhydra/plugins/attr/Makefile.in
@@ -0,0 +1,586 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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/attr
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_attr_la_LIBADD =
+am_libstrongswan_attr_la_OBJECTS = attr_plugin.lo attr_provider.lo
+libstrongswan_attr_la_OBJECTS = $(am_libstrongswan_attr_la_OBJECTS)
+libstrongswan_attr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_attr_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_attr_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_attr_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_attr_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_attr_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-attr.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-attr.la
+libstrongswan_attr_la_SOURCES = \
+ attr_plugin.h attr_plugin.c \
+ attr_provider.h attr_provider.c
+
+libstrongswan_attr_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/attr/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libhydra/plugins/attr/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-attr.la: $(libstrongswan_attr_la_OBJECTS) $(libstrongswan_attr_la_DEPENDENCIES)
+ $(libstrongswan_attr_la_LINK) $(am_libstrongswan_attr_la_rpath) $(libstrongswan_attr_la_OBJECTS) $(libstrongswan_attr_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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 all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libhydra/plugins/attr/attr_plugin.c b/src/libhydra/plugins/attr/attr_plugin.c
new file mode 100644
index 000000000..24c00bb44
--- /dev/null
+++ b/src/libhydra/plugins/attr/attr_plugin.c
@@ -0,0 +1,63 @@
+/*
+ * 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 "attr_plugin.h"
+#include "attr_provider.h"
+
+#include <hydra.h>
+
+typedef struct private_attr_plugin_t private_attr_plugin_t;
+
+/**
+ * private data of attr plugin
+ */
+struct private_attr_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ attr_plugin_t public;
+
+ /**
+ * CFG attributes provider
+ */
+ attr_provider_t *provider;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_attr_plugin_t *this)
+{
+ hydra->attributes->remove_provider(hydra->attributes, &this->provider->provider);
+ this->provider->destroy(this->provider);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *attr_plugin_create()
+{
+ private_attr_plugin_t *this = malloc_thing(private_attr_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->provider = attr_provider_create();
+ hydra->attributes->add_provider(hydra->attributes, &this->provider->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libhydra/plugins/attr/attr_plugin.h b/src/libhydra/plugins/attr/attr_plugin.h
new file mode 100644
index 000000000..29fb33839
--- /dev/null
+++ b/src/libhydra/plugins/attr/attr_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 attr attr
+ * @ingroup hplugins
+ *
+ * @defgroup attr_plugin attr_plugin
+ * @{ @ingroup attr
+ */
+
+#ifndef ATTR_PLUGIN_H_
+#define ATTR_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct attr_plugin_t attr_plugin_t;
+
+/**
+ * Plugin providing configuration attribute through strongswan.conf.
+ */
+struct attr_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** ATTR_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/attr/attr_provider.c b/src/libhydra/plugins/attr/attr_provider.c
new file mode 100644
index 000000000..9d6daa892
--- /dev/null
+++ b/src/libhydra/plugins/attr/attr_provider.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * 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 "attr_provider.h"
+
+#include <time.h>
+
+#include <hydra.h>
+#include <debug.h>
+#include <utils/linked_list.h>
+
+#define SERVER_MAX 2
+
+typedef struct private_attr_provider_t private_attr_provider_t;
+typedef struct attribute_entry_t attribute_entry_t;
+
+/**
+ * private data of attr_provider
+ */
+struct private_attr_provider_t {
+
+ /**
+ * public functions
+ */
+ attr_provider_t public;
+
+ /**
+ * List of attributes, attribute_entry_t
+ */
+ linked_list_t *attributes;
+};
+
+struct attribute_entry_t {
+ /** type of attribute */
+ configuration_attribute_type_t type;
+ /** attribute value */
+ chunk_t value;
+};
+
+/**
+ * convert enumerator value from attribute_entry
+ */
+static bool attr_enum_filter(void *null, attribute_entry_t **in,
+ configuration_attribute_type_t *type, void* none, chunk_t *value)
+{
+ *type = (*in)->type;
+ *value = (*in)->value;
+ return TRUE;
+}
+
+/**
+ * Implementation of attribute_provider_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
+ identification_t *id, host_t *vip)
+{
+ if (vip)
+ {
+ return enumerator_create_filter(
+ this->attributes->create_enumerator(this->attributes),
+ (void*)attr_enum_filter, NULL, NULL);
+ }
+ return enumerator_create_empty();
+}
+
+/**
+ * Implementation of attr_provider_t.destroy
+ */
+static void destroy(private_attr_provider_t *this)
+{
+ attribute_entry_t *entry;
+
+ while (this->attributes->remove_last(this->attributes,
+ (void**)&entry) == SUCCESS)
+ {
+ free(entry->value.ptr);
+ free(entry);
+ }
+ this->attributes->destroy(this->attributes);
+ free(this);
+}
+
+/**
+ * Add an attribute entry to the list
+ */
+static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
+ configuration_attribute_type_t type)
+{
+ attribute_entry_t *entry;
+ host_t *host;
+ char *str;
+
+ str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, hydra->daemon,
+ key, nr);
+ if (str)
+ {
+ host = host_create_from_string(str, 0);
+ if (host)
+ {
+ entry = malloc_thing(attribute_entry_t);
+
+ if (host->get_family(host) == AF_INET6)
+ {
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ type = INTERNAL_IP6_DNS;
+ break;
+ case INTERNAL_IP4_NBNS:
+ type = INTERNAL_IP6_NBNS;
+ break;
+ default:
+ break;
+ }
+ }
+ entry->type = type;
+ entry->value = chunk_clone(host->get_address(host));
+ host->destroy(host);
+ this->attributes->insert_last(this->attributes, entry);
+ }
+ }
+}
+
+/**
+ * Key to attribute type mappings, for v4 and v6 attributes
+ */
+static 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},
+};
+
+/**
+ * Load (numerical) entries from the plugins.attr namespace
+ */
+static void load_entries(private_attr_provider_t *this)
+{
+ enumerator_t *enumerator, *tokens;
+ char *key, *value, *token;
+
+ enumerator = lib->settings->create_key_value_enumerator(lib->settings,
+ "%s.plugins.attr", hydra->daemon);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ configuration_attribute_type_t type;
+ attribute_entry_t *entry;
+ host_t *host;
+ int i;
+
+ type = atoi(key);
+ tokens = enumerator_create_token(value, ",", " ");
+ while (tokens->enumerate(tokens, &token))
+ {
+ host = host_create_from_string(token, 0);
+ if (!host)
+ {
+ DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
+ continue;
+ }
+ if (!type)
+ {
+ for (i = 0; i < countof(keys); i++)
+ {
+ if (streq(key, keys[i].name))
+ {
+ if (host->get_family(host) == AF_INET)
+ {
+ type = keys[i].v4;
+ }
+ else
+ {
+ type = keys[i].v6;
+ }
+ }
+ }
+ if (!type)
+ {
+ DBG1(DBG_CFG, "mapping attribute type %s failed", key);
+ break;
+ }
+ }
+ entry = malloc_thing(attribute_entry_t);
+ entry->type = type;
+ entry->value = chunk_clone(host->get_address(host));
+ host->destroy(host);
+ this->attributes->insert_last(this->attributes, entry);
+ }
+ tokens->destroy(tokens);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/*
+ * see header file
+ */
+attr_provider_t *attr_provider_create(database_t *db)
+{
+ private_attr_provider_t *this;
+ int i;
+
+ this = malloc_thing(private_attr_provider_t);
+
+ this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null;
+ this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false;
+ this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))create_attribute_enumerator;
+ this->public.destroy = (void(*)(attr_provider_t*))destroy;
+
+ this->attributes = linked_list_create();
+
+ for (i = 1; i <= SERVER_MAX; i++)
+ {
+ add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS);
+ add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS);
+ }
+
+ load_entries(this);
+
+ return &this->public;
+}
+
diff --git a/src/libhydra/plugins/attr/attr_provider.h b/src/libhydra/plugins/attr/attr_provider.h
new file mode 100644
index 000000000..a41466718
--- /dev/null
+++ b/src/libhydra/plugins/attr/attr_provider.h
@@ -0,0 +1,49 @@
+/*
+ * 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 attr_provider attr_provider
+ * @{ @ingroup attr
+ */
+
+#ifndef ATTR_PROVIDER_H_
+#define ATTR_PROVIDER_H_
+
+#include <attributes/attribute_provider.h>
+
+typedef struct attr_provider_t attr_provider_t;
+
+/**
+ * Provide configuration attributes through static strongswan.conf definition.
+ */
+struct attr_provider_t {
+
+ /**
+ * Implements attribute provider interface
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Destroy a attr_provider instance.
+ */
+ void (*destroy)(attr_provider_t *this);
+};
+
+/**
+ * Create a attr_provider instance.
+ */
+attr_provider_t *attr_provider_create();
+
+#endif /** ATTR_PROVIDER @}*/
diff --git a/src/libhydra/plugins/attr_sql/Makefile.am b/src/libhydra/plugins/attr_sql/Makefile.am
new file mode 100644
index 000000000..376a8259c
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/Makefile.am
@@ -0,0 +1,23 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra
+
+AM_CFLAGS = \
+ -rdynamic \
+ -DPLUGINS=\""${libstrongswan_plugins}\""
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-attr-sql.la
+else
+plugin_LTLIBRARIES = libstrongswan-attr-sql.la
+endif
+
+libstrongswan_attr_sql_la_SOURCES = \
+ attr_sql_plugin.h attr_sql_plugin.c \
+ sql_attribute.h sql_attribute.c
+
+libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version
+
+ipsec_PROGRAMS = pool
+pool_SOURCES = pool.c
+pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+pool.o : $(top_builddir)/config.status
diff --git a/src/libhydra/plugins/attr_sql/Makefile.in b/src/libhydra/plugins/attr_sql/Makefile.in
new file mode 100644
index 000000000..99e97cefc
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/Makefile.in
@@ -0,0 +1,649 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+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@
+ipsec_PROGRAMS = pool$(EXEEXT)
+subdir = src/libhydra/plugins/attr_sql
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+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/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+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__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_attr_sql_la_LIBADD =
+am_libstrongswan_attr_sql_la_OBJECTS = attr_sql_plugin.lo \
+ sql_attribute.lo
+libstrongswan_attr_sql_la_OBJECTS = \
+ $(am_libstrongswan_attr_sql_la_OBJECTS)
+libstrongswan_attr_sql_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_attr_sql_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_attr_sql_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_attr_sql_la_rpath =
+PROGRAMS = $(ipsec_PROGRAMS)
+am_pool_OBJECTS = pool.$(OBJEXT)
+pool_OBJECTS = $(am_pool_OBJECTS)
+pool_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+DEFAULT_INCLUDES = -I.@am__isrc@
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_attr_sql_la_SOURCES) $(pool_SOURCES)
+DIST_SOURCES = $(libstrongswan_attr_sql_la_SOURCES) $(pool_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_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@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+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@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra
+AM_CFLAGS = \
+ -rdynamic \
+ -DPLUGINS=\""${libstrongswan_plugins}\""
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-attr-sql.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-attr-sql.la
+libstrongswan_attr_sql_la_SOURCES = \
+ attr_sql_plugin.h attr_sql_plugin.c \
+ sql_attribute.h sql_attribute.c
+
+libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version
+pool_SOURCES = pool.c
+pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/plugins/attr_sql/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libhydra/plugins/attr_sql/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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ 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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-attr-sql.la: $(libstrongswan_attr_sql_la_OBJECTS) $(libstrongswan_attr_sql_la_DEPENDENCIES)
+ $(libstrongswan_attr_sql_la_LINK) $(am_libstrongswan_attr_sql_la_rpath) $(libstrongswan_attr_sql_la_OBJECTS) $(libstrongswan_attr_sql_la_LIBADD) $(LIBS)
+install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ 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)$(ipsecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-ipsecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || 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)$(ipsecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
+
+clean-ipsecPROGRAMS:
+ @list='$(ipsec_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
+pool$(EXEEXT): $(pool_OBJECTS) $(pool_DEPENDENCIES)
+ @rm -f pool$(EXEEXT)
+ $(LINK) $(pool_OBJECTS) $(pool_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_sql_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_attribute.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(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)" "$(DESTDIR)$(ipsecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -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-ipsecPROGRAMS 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-ipsecPROGRAMS 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-ipsecPROGRAMS uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-ipsecPROGRAMS clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-ipsecPROGRAMS install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-ipsecPROGRAMS \
+ uninstall-pluginLTLIBRARIES
+
+pool.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/libhydra/plugins/attr_sql/attr_sql_plugin.c b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c
new file mode 100644
index 000000000..70e7a2247
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#include <hydra.h>
+#include <debug.h>
+
+#include "attr_sql_plugin.h"
+#include "sql_attribute.h"
+
+typedef struct private_attr_sql_plugin_t private_attr_sql_plugin_t;
+
+/**
+ * private data of attr_sql plugin
+ */
+struct private_attr_sql_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ attr_sql_plugin_t public;
+
+ /**
+ * database connection instance
+ */
+ database_t *db;
+
+ /**
+ * configuration attributes
+ */
+ sql_attribute_t *attribute;
+
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_attr_sql_plugin_t *this)
+{
+ hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ this->attribute->destroy(this->attribute);
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *attr_sql_plugin_create()
+{
+ char *uri;
+ private_attr_sql_plugin_t *this;
+
+ uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", NULL);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "attr-sql plugin: database URI not set");
+ return NULL;
+ }
+
+ this = malloc_thing(private_attr_sql_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->db = lib->db->create(lib->db, uri);
+ if (!this->db)
+ {
+ DBG1(DBG_CFG, "attr-sql plugin failed to connect to database");
+ free(this);
+ return NULL;
+ }
+ this->attribute = sql_attribute_create(this->db);
+ hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libhydra/plugins/attr_sql/attr_sql_plugin.h b/src/libhydra/plugins/attr_sql/attr_sql_plugin.h
new file mode 100644
index 000000000..ba85a6b28
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/attr_sql_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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 attr_sql attr_sql
+ * @ingroup hplugins
+ *
+ * @defgroup sql_plugin sql_plugin
+ * @{ @ingroup attr_sql
+ */
+
+#ifndef ATTR_SQL_PLUGIN_H_
+#define ATTR_SQL_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct attr_sql_plugin_t attr_sql_plugin_t;
+
+/**
+ * SQL database attribute configuration plugin
+ */
+struct attr_sql_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** ATTR_SQL_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/attr_sql/pool.c b/src/libhydra/plugins/attr_sql/pool.c
new file mode 100644
index 000000000..fed89fc51
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/pool.c
@@ -0,0 +1,1402 @@
+/*
+ * 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 <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <library.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <attributes/attributes.h>
+
+/**
+ * global database handle
+ */
+database_t *db;
+
+/**
+ * --start/--end/--server addresses of various subcommands
+ */
+host_t *start = NULL, *end = NULL, *server = NULL;
+
+/**
+ * whether --add should --replace an existing pool
+ */
+bool replace_pool = FALSE;
+
+/**
+ * forward declarations
+ */
+static void del(char *name);
+static void do_args(int argc, char *argv[]);
+
+/**
+ * nesting counter for database transaction functions
+ */
+int nested_transaction = 0;
+
+/**
+ * start a database transaction
+ */
+static void begin_transaction()
+{
+ if (db->get_driver(db) == DB_SQLITE)
+ {
+ if (!nested_transaction)
+ {
+ db->execute(db, NULL, "BEGIN EXCLUSIVE TRANSACTION");
+ }
+ ++nested_transaction;
+ }
+}
+
+/**
+ * commit a database transaction
+ */
+static void commit_transaction()
+{
+ if (db->get_driver(db) == DB_SQLITE)
+ {
+ --nested_transaction;
+ if (!nested_transaction)
+ {
+ db->execute(db, NULL, "END TRANSACTION");
+ }
+ }
+}
+
+/**
+ * Create or replace a pool by name
+ */
+static u_int create_pool(char *name, chunk_t start, chunk_t end, int timeout)
+{
+ enumerator_t *e;
+ int pool;
+
+ e = db->query(db, "SELECT id FROM pools WHERE name = ?",
+ DB_TEXT, name, DB_UINT);
+ if (e && e->enumerate(e, &pool))
+ {
+ if (replace_pool == FALSE)
+ {
+ fprintf(stderr, "pool '%s' exists.\n", name);
+ e->destroy(e);
+ exit(EXIT_FAILURE);
+ }
+ del(name);
+ }
+ DESTROY_IF(e);
+ if (db->execute(db, &pool,
+ "INSERT INTO pools (name, start, end, timeout) VALUES (?, ?, ?, ?)",
+ DB_TEXT, name, DB_BLOB, start, DB_BLOB, end,
+ DB_INT, timeout*3600) != 1)
+ {
+ fprintf(stderr, "creating pool failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return pool;
+}
+
+/**
+ * instead of a pool handle a DNS or NBNS attribute
+ */
+static bool is_attribute(char *name)
+{
+ return strcaseeq(name, "dns") || strcaseeq(name, "nbns") ||
+ strcaseeq(name, "wins");
+}
+
+/**
+ * determine configuration attribute type
+ */
+static configuration_attribute_type_t get_attribute_type(char *name, host_t* addr)
+{
+ if (strcaseeq(name, "dns"))
+ {
+ return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_DNS :
+ INTERNAL_IP6_DNS;
+ }
+ else
+ {
+ return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_NBNS :
+ INTERNAL_IP6_NBNS;
+ }
+}
+
+/**
+ * calculate the size of a pool using start and end address chunk
+ */
+static u_int get_pool_size(chunk_t start, chunk_t end)
+{
+ u_int *start_ptr, *end_ptr;
+
+ if (start.len < sizeof(u_int) || end.len < sizeof(u_int))
+ {
+ return 0;
+ }
+ start_ptr = (u_int*)(start.ptr + start.len - sizeof(u_int));
+ end_ptr = (u_int*)(end.ptr + end.len - sizeof(u_int));
+ return ntohl(*end_ptr) - ntohl(*start_ptr) + 1;
+}
+
+/**
+ * print usage info
+ */
+static void usage(void)
+{
+ printf("\
+Usage:\n\
+ ipsec pool --status|--add|--replace|--del|--resize|--purge [options]\n\
+ \n\
+ ipsec pool --status\n\
+ Show a list of installed pools with statistics.\n\
+ \n\
+ ipsec pool --add <name> --start <start> --end <end> [--timeout <timeout>]\n\
+ ipsec pool --replace <name> --start <start> --end <end> [--timeout <timeout>]\n\
+ Add a new pool to or replace an existing pool in the database.\n\
+ name: Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
+ start: Start address of the pool\n\
+ end: End address of the pool\n\
+ timeout: Lease time in hours, 0 for static leases\n\
+ \n\
+ ipsec pool --add <name> --addresses <file> [--timeout <timeout>]\n\
+ ipsec pool --replace <name> --addresses <file> [--timeout <timeout>]\n\
+ Add a new pool to or replace an existing pool in the database.\n\
+ name: Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
+ file: File newline separated addresses for the pool are read from.\n\
+ Optionally each address can be pre-assigned to a roadwarrior\n\
+ identity, e.g. 10.231.14.2=alice@strongswan.org.\n\
+ If a - (hyphen) is given instead of a file name, the addresses\n\
+ are read from STDIN. Reading addresses stops at the end of file\n\
+ or an empty line. Pools created with this command can not be\n\
+ resized.\n\
+ timeout: Lease time in hours, 0 for static leases\n\
+ \n\
+ ipsec pool --add dns|nbns|wins --server <server>\n\
+ Add a new DNS or NBNS server to the database.\n\
+ server: IP address of the name server\n\
+ \n\
+ ipsec pool --del <name>\n\
+ Delete a pool from the database.\n\
+ name: Name of the pool to delete\n\
+ \n\
+ ipsec pool --del dns|nbns|wins [--server <server>]\n\
+ Delete a specific or all DNS or NBNS servers from the database.\n\
+ server: IP address of the name server to delete\n\
+ \n\
+ ipsec pool --resize <name> --end <end>\n\
+ Grow or shrink an existing pool.\n\
+ name: Name of the pool to resize\n\
+ end: New end address for the pool\n\
+ \n\
+ ipsec pool --leases [--filter <filter>] [--utc]\n\
+ Show lease information using filters:\n\
+ filter: Filter string containing comma separated key=value filters,\n\
+ e.g. id=alice@strongswan.org,addr=1.1.1.1\n\
+ pool: name of the pool\n\
+ id: assigned identity of the lease\n\
+ addr: lease IP address\n\
+ tstamp: UNIX timestamp when lease was valid, as integer\n\
+ status: status of the lease: online|valid|expired\n\
+ utc: Show times in UTC instead of local time\n\
+ \n\
+ ipsec pool --purge <name>\n\
+ Delete lease history of a pool:\n\
+ name: Name of the pool to purge\n\
+ \n\
+ ipsec pool --batch <file>\n\
+ Read commands from a file and execute them atomically.\n\
+ file: File to read the newline separated commands from. Commands\n\
+ appear as they are written on the command line, e.g.\n\
+ --replace mypool --start 10.0.0.1 --end 10.0.0.254\n\
+ --del dns\n\
+ --add dns --server 10.1.0.1\n\
+ --add dns --server 10.1.1.1\n\
+ If a - (hyphen) is given as a file name, the commands are read\n\
+ from STDIN. Readin commands stops at the end of file. Empty\n\
+ lines are ignored. The file may not contain a --batch command.\n\
+ \n");
+}
+
+/**
+ * ipsec pool --status - show pool overview
+ */
+static void status(void)
+{
+ enumerator_t *ns, *pool, *lease;
+ host_t *server;
+ chunk_t value;
+ bool found = FALSE;
+
+ /* enumerate IPv4 DNS servers */
+ ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+ DB_INT, INTERNAL_IP4_DNS, DB_BLOB);
+ if (ns)
+ {
+ while (ns->enumerate(ns, &value))
+ {
+ if (!found)
+ {
+ printf("dns servers:");
+ found = TRUE;
+ }
+ server = host_create_from_chunk(AF_INET, value, 0);
+ if (server)
+ {
+ printf(" %H", server);
+ server->destroy(server);
+ }
+ }
+ ns->destroy(ns);
+ }
+
+ /* enumerate IPv6 DNS servers */
+ ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+ DB_INT, INTERNAL_IP6_DNS, DB_BLOB);
+ if (ns)
+ {
+ while (ns->enumerate(ns, &value))
+ {
+ if (!found)
+ {
+ printf("dns servers:");
+ found = TRUE;
+ }
+ server = host_create_from_chunk(AF_INET6, value, 0);
+ if (server)
+ {
+ printf(" %H", server);
+ server->destroy(server);
+ }
+ }
+ ns->destroy(ns);
+ }
+ if (found)
+ {
+ printf("\n");
+ }
+ else
+ {
+ printf("no dns servers found.\n");
+ }
+ found = FALSE;
+
+ /* enumerate IPv4 NBNS servers */
+ ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+ DB_INT, INTERNAL_IP4_NBNS, DB_BLOB);
+ if (ns)
+ {
+ while (ns->enumerate(ns, &value))
+ {
+ if (!found)
+ {
+ printf("nbns servers:");
+ found = TRUE;
+ }
+ server = host_create_from_chunk(AF_INET, value, 0);
+ if (server)
+ {
+ printf(" %H", server);
+ server->destroy(server);
+ }
+ }
+ ns->destroy(ns);
+ }
+
+ /* enumerate IPv6 NBNS servers */
+ ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+ DB_INT, INTERNAL_IP6_NBNS, DB_BLOB);
+ if (ns)
+ {
+ while (ns->enumerate(ns, &value))
+ {
+ if (!found)
+ {
+ printf("nbns servers:");
+ found = TRUE;
+ }
+ server = host_create_from_chunk(AF_INET6, value, 0);
+ if (server)
+ {
+ printf(" %H", server);
+ server->destroy(server);
+ }
+ }
+ ns->destroy(ns);
+ }
+ if (found)
+ {
+ printf("\n");
+ }
+ else
+ {
+ printf("no nbns servers found.\n");
+ }
+ found = FALSE;
+
+ pool = db->query(db, "SELECT id, name, start, end, timeout FROM pools",
+ DB_INT, DB_TEXT, DB_BLOB, DB_BLOB, DB_UINT);
+ if (pool)
+ {
+ char *name;
+ chunk_t start_chunk, end_chunk;
+ host_t *start, *end;
+ u_int id, timeout, online = 0, used = 0, size = 0;
+
+ while (pool->enumerate(pool, &id, &name,
+ &start_chunk, &end_chunk, &timeout))
+ {
+ if (!found)
+ {
+ printf("%8s %15s %15s %8s %6s %11s %11s\n", "name", "start",
+ "end", "timeout", "size", "online", "usage");
+ found = TRUE;
+ }
+
+ start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
+ end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
+ if (start->is_anyaddr(start) && end->is_anyaddr(end))
+ {
+ printf("%8s %15s %15s ", name, "n/a", "n/a");
+ }
+ else
+ {
+ printf("%8s %15H %15H ", name, start, end);
+ }
+ if (timeout)
+ {
+ printf("%7dh ", timeout/3600);
+ }
+ else
+ {
+ printf("%8s ", "static");
+ }
+ /* get total number of hosts in the pool */
+ lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+ "WHERE pool = ?", DB_UINT, id, DB_INT);
+ if (lease)
+ {
+ lease->enumerate(lease, &size);
+ lease->destroy(lease);
+ }
+ printf("%6d ", size);
+ /* get number of online hosts */
+ lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+ "WHERE pool = ? AND released = 0",
+ DB_UINT, id, DB_INT);
+ if (lease)
+ {
+ lease->enumerate(lease, &online);
+ lease->destroy(lease);
+ }
+ printf("%5d (%2d%%) ", online, online*100/size);
+ /* get number of online or valid lieases */
+ lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+ "WHERE addresses.pool = ? "
+ "AND ((? AND acquired != 0) "
+ " OR released = 0 OR released > ?) ",
+ DB_UINT, id, DB_UINT, !timeout,
+ DB_UINT, time(NULL) - timeout, DB_UINT);
+ if (lease)
+ {
+ lease->enumerate(lease, &used);
+ lease->destroy(lease);
+ }
+ printf("%5d (%2d%%) ", used, used*100/size);
+
+ printf("\n");
+ DESTROY_IF(start);
+ DESTROY_IF(end);
+ }
+ pool->destroy(pool);
+ }
+ if (!found)
+ {
+ printf("no pools found.\n");
+ }
+}
+
+/**
+ * ipsec pool --add - add a new pool
+ */
+static void add(char *name, host_t *start, host_t *end, int timeout)
+{
+ chunk_t start_addr, end_addr, cur_addr;
+ u_int id, count;
+
+ start_addr = start->get_address(start);
+ end_addr = end->get_address(end);
+ cur_addr = chunk_clonea(start_addr);
+ count = get_pool_size(start_addr, end_addr);
+
+ if (start_addr.len != end_addr.len ||
+ memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0)
+ {
+ fprintf(stderr, "invalid start/end pair specified.\n");
+ exit(EXIT_FAILURE);
+ }
+ id = create_pool(name, start_addr, end_addr, timeout);
+ printf("allocating %d addresses... ", count);
+ fflush(stdout);
+ /* run population in a transaction for sqlite */
+ begin_transaction();
+ while (TRUE)
+ {
+ db->execute(db, NULL,
+ "INSERT INTO addresses (pool, address, identity, acquired, released) "
+ "VALUES (?, ?, ?, ?, ?)",
+ DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
+ if (chunk_equals(cur_addr, end_addr))
+ {
+ break;
+ }
+ chunk_increment(cur_addr);
+ }
+ commit_transaction();
+ printf("done.\n", count);
+}
+
+static bool add_address(u_int pool_id, char *address_str, int *family)
+{
+ host_t *address;
+ int user_id = 0;
+
+ char *pos_eq = strchr(address_str, '=');
+ if (pos_eq != NULL)
+ {
+ enumerator_t *e;
+ identification_t *id = identification_create_from_string(pos_eq + 1);
+
+ /* look for peer identity in the identities table */
+ e = db->query(db,
+ "SELECT id FROM identities WHERE type = ? AND data = ?",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_UINT);
+
+ if (!e || !e->enumerate(e, &user_id))
+ {
+ /* not found, insert new one */
+ if (db->execute(db, &user_id,
+ "INSERT INTO identities (type, data) VALUES (?, ?)",
+ DB_INT, id->get_type(id),
+ DB_BLOB, id->get_encoding(id)) != 1)
+ {
+ fprintf(stderr, "creating id '%s' failed.\n", pos_eq + 1);
+ return FALSE;
+ }
+ }
+ DESTROY_IF(e);
+ id->destroy(id);
+ *pos_eq = '\0';
+ }
+
+ address = host_create_from_string(address_str, 0);
+ if (address == NULL)
+ {
+ fprintf(stderr, "invalid address '%s'.\n", address_str);
+ return FALSE;
+ }
+ if (family && *family && *family != address->get_family(address))
+ {
+ fprintf(stderr, "invalid address family '%s'.\n", address_str);
+ return FALSE;
+ }
+
+ if (db->execute(db, NULL,
+ "INSERT INTO addresses "
+ "(pool, address, identity, acquired, released) "
+ "VALUES (?, ?, ?, ?, ?)",
+ DB_UINT, pool_id, DB_BLOB, address->get_address(address),
+ DB_UINT, user_id, DB_UINT, 0, DB_UINT, 1) != 1)
+ {
+ fprintf(stderr, "inserting address '%s' failed.\n", address_str);
+ return FALSE;
+ }
+ *family = address->get_family(address);
+ address->destroy(address);
+
+ return TRUE;
+}
+
+static void add_addresses(char *pool, char *path, int timeout)
+{
+ u_int pool_id, count = 0;
+ int family = AF_UNSPEC;
+ char address_str[512];
+ host_t *addr;
+ FILE *file;
+
+ /* run population in a transaction for sqlite */
+ begin_transaction();
+
+ addr = host_create_from_string("%any", 0);
+ pool_id = create_pool(pool, addr->get_address(addr),
+ addr->get_address(addr), timeout);
+ addr->destroy(addr);
+
+ file = (strcmp(path, "-") == 0 ? stdin : fopen(path, "r"));
+ if (file == NULL)
+ {
+ fprintf(stderr, "opening '%s' failed: %s\n", path, strerror(errno));
+ exit(-1);
+ }
+
+ printf("starting allocation... ");
+ fflush(stdout);
+
+ while (fgets(address_str, sizeof(address_str), file))
+ {
+ size_t addr_len = strlen(address_str);
+ char *last_chr = address_str + addr_len - 1;
+ if (*last_chr == '\n')
+ {
+ if (addr_len == 1)
+ { /* end of input */
+ break;
+ }
+ *last_chr = '\0';
+ }
+ if (add_address(pool_id, address_str, &family) == FALSE)
+ {
+ exit(EXIT_FAILURE);
+ }
+ ++count;
+ }
+
+ if (file != stdin)
+ {
+ fclose(file);
+ }
+
+ commit_transaction();
+
+ printf("%d addresses done.\n", count);
+}
+
+/**
+ * ipsec pool --add dns|nbns|wins - add a DNS or NBNS server entry
+ */
+static void add_attr(char *name, host_t *server)
+{
+ configuration_attribute_type_t type;
+ chunk_t value;
+
+ type = get_attribute_type(name, server);
+ value = server->get_address(server);
+ if (db->execute(db, NULL,
+ "INSERT INTO attributes (type, value) VALUES (?, ?)",
+ DB_INT, type, DB_BLOB, value) != 1)
+ {
+ fprintf(stderr, "adding %s server %H failed.\n", name, server);
+ exit(EXIT_FAILURE);
+ }
+ printf("added %s server %H\n", name, server);
+}
+
+/**
+ * ipsec pool --del - delete a pool
+ */
+static void del(char *name)
+{
+ enumerator_t *query;
+ u_int id;
+ bool found = FALSE;
+
+ query = db->query(db, "SELECT id FROM pools WHERE name = ?",
+ DB_TEXT, name, DB_UINT);
+ if (!query)
+ {
+ fprintf(stderr, "deleting pool failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ while (query->enumerate(query, &id))
+ {
+ found = TRUE;
+ if (db->execute(db, NULL,
+ "DELETE FROM leases WHERE address IN ("
+ " SELECT id FROM addresses WHERE pool = ?)", DB_UINT, id) < 0 ||
+ db->execute(db, NULL,
+ "DELETE FROM addresses WHERE pool = ?", DB_UINT, id) < 0 ||
+ db->execute(db, NULL,
+ "DELETE FROM pools WHERE id = ?", DB_UINT, id) < 0)
+ {
+ fprintf(stderr, "deleting pool failed.\n");
+ query->destroy(query);
+ exit(EXIT_FAILURE);
+ }
+ }
+ query->destroy(query);
+ if (!found)
+ {
+ fprintf(stderr, "pool '%s' not found.\n", name);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/**
+ * ipsec pool --del dns|nbns|wins - delete a DNS or NBNS server entry
+ */
+static void del_attr(char *name, host_t *server)
+{
+ configuration_attribute_type_t type;
+ chunk_t value;
+ u_int id;
+ enumerator_t *query;
+ bool found = FALSE;
+
+ if (server)
+ {
+ type = get_attribute_type(name, server);
+ value = server->get_address(server);
+ query = db->query(db,
+ "SELECT id, type, value FROM attributes "
+ "WHERE type = ? AND value = ?",
+ DB_INT, type, DB_BLOB, value,
+ DB_UINT, DB_INT, DB_BLOB);
+ }
+ else
+ {
+ configuration_attribute_type_t type_ip4, type_ip6;
+
+ if (strcaseeq(name, "dns"))
+ {
+ type_ip4 = INTERNAL_IP4_DNS;
+ type_ip6 = INTERNAL_IP6_DNS;
+ }
+ else
+ {
+ type_ip4 = INTERNAL_IP4_NBNS;
+ type_ip6 = INTERNAL_IP6_NBNS;
+ }
+
+ query = db->query(db,
+ "SELECT id, type, value FROM attributes "
+ "WHERE type = ? OR type = ?",
+ DB_INT, type_ip4, DB_INT, type_ip6,
+ DB_UINT, DB_INT, DB_BLOB);
+ }
+ if (!query)
+ {
+ fprintf(stderr, "deleting %s servers failed.\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ while (query->enumerate(query, &id, &type, &value))
+ {
+ int family;
+ host_t *host;
+
+ found = TRUE;
+ family = (type == INTERNAL_IP4_DNS || type == INTERNAL_IP4_NBNS) ?
+ AF_INET : AF_INET6;
+ host = host_create_from_chunk(family, value, 0);
+ if (db->execute(db, NULL,
+ "DELETE FROM attributes WHERE id = ?",
+ DB_UINT, id) != 1)
+ {
+ fprintf(stderr, "deleting %s server %H failed\n", name, host);
+ query->destroy(query);
+ DESTROY_IF(host);
+ exit(EXIT_FAILURE);
+ }
+ printf("deleted %s server %H\n", name, host);
+ DESTROY_IF(host);
+ }
+ query->destroy(query);
+
+ if (!found && server)
+ {
+ printf("%s server %H not found\n", name, server);
+ exit(EXIT_FAILURE);
+ }
+ else if (!found)
+ {
+ printf("no %s servers found\n", name);
+ }
+}
+
+/**
+ * ipsec pool --resize - resize a pool
+ */
+static void resize(char *name, host_t *end)
+{
+ enumerator_t *query;
+ chunk_t old_addr, new_addr, cur_addr;
+ u_int id, count;
+ host_t *old_end;
+
+ new_addr = end->get_address(end);
+
+ query = db->query(db, "SELECT id, end FROM pools WHERE name = ?",
+ DB_TEXT, name, DB_UINT, DB_BLOB);
+ if (!query || !query->enumerate(query, &id, &old_addr))
+ {
+ DESTROY_IF(query);
+ fprintf(stderr, "resizing pool failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ if (old_addr.len != new_addr.len ||
+ memcmp(new_addr.ptr, old_addr.ptr, old_addr.len) < 0)
+ {
+ fprintf(stderr, "shrinking of pools not supported.\n");
+ query->destroy(query);
+ exit(EXIT_FAILURE);
+ }
+ cur_addr = chunk_clonea(old_addr);
+ count = get_pool_size(old_addr, new_addr) - 1;
+ query->destroy(query);
+
+ /* Check whether pool is resizable */
+ old_end = host_create_from_chunk(AF_UNSPEC, old_addr, 0);
+ if (old_end && old_end->is_anyaddr(old_end))
+ {
+ fprintf(stderr, "pool is not resizable.\n");
+ old_end->destroy(old_end);
+ exit(EXIT_FAILURE);
+ }
+ DESTROY_IF(old_end);
+
+ if (db->execute(db, NULL,
+ "UPDATE pools SET end = ? WHERE name = ?",
+ DB_BLOB, new_addr, DB_TEXT, name) <= 0)
+ {
+ fprintf(stderr, "pool '%s' not found.\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("allocating %d new addresses... ", count);
+ fflush(stdout);
+ /* run population in a transaction for sqlite */
+ begin_transaction();
+ while (count-- > 0)
+ {
+ chunk_increment(cur_addr);
+ db->execute(db, NULL,
+ "INSERT INTO addresses (pool, address, identity, acquired, released) "
+ "VALUES (?, ?, ?, ?, ?)",
+ DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
+ }
+ commit_transaction();
+ printf("done.\n", count);
+
+}
+
+/**
+ * create the lease query using the filter string
+ */
+static enumerator_t *create_lease_query(char *filter)
+{
+ enumerator_t *query;
+ identification_t *id = NULL;
+ host_t *addr = NULL;
+ u_int tstamp = 0;
+ bool online = FALSE, valid = FALSE, expired = FALSE;
+ char *value, *pos, *pool = NULL;
+ enum {
+ FIL_POOL = 0,
+ FIL_ID,
+ FIL_ADDR,
+ FIL_TSTAMP,
+ FIL_STATE,
+ };
+ char *const token[] = {
+ [FIL_POOL] = "pool",
+ [FIL_ID] = "id",
+ [FIL_ADDR] = "addr",
+ [FIL_TSTAMP] = "tstamp",
+ [FIL_STATE] = "status",
+ NULL
+ };
+
+ /* if the filter string contains a distinguished name as a ID, we replace
+ * ", " by "/ " in order to not confuse the getsubopt parser */
+ pos = filter;
+ while ((pos = strchr(pos, ',')))
+ {
+ if (pos[1] == ' ')
+ {
+ pos[0] = '/';
+ }
+ pos++;
+ }
+
+ while (filter && *filter != '\0')
+ {
+ switch (getsubopt(&filter, token, &value))
+ {
+ case FIL_POOL:
+ if (value)
+ {
+ pool = value;
+ }
+ break;
+ case FIL_ID:
+ if (value)
+ {
+ id = identification_create_from_string(value);
+ }
+ break;
+ case FIL_ADDR:
+ if (value)
+ {
+ addr = host_create_from_string(value, 0);
+ }
+ if (!addr)
+ {
+ fprintf(stderr, "invalid 'addr' in filter string.\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case FIL_TSTAMP:
+ if (value)
+ {
+ tstamp = atoi(value);
+ }
+ if (tstamp == 0)
+ {
+ online = TRUE;
+ }
+ break;
+ case FIL_STATE:
+ if (value)
+ {
+ if (streq(value, "online"))
+ {
+ online = TRUE;
+ }
+ else if (streq(value, "valid"))
+ {
+ valid = TRUE;
+ }
+ else if (streq(value, "expired"))
+ {
+ expired = TRUE;
+ }
+ else
+ {
+ fprintf(stderr, "invalid 'state' in filter string.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "invalid filter string.\n");
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+ query = db->query(db,
+ "SELECT name, addresses.address, identities.type, "
+ "identities.data, leases.acquired, leases.released, timeout "
+ "FROM leases JOIN addresses ON leases.address = addresses.id "
+ "JOIN pools ON addresses.pool = pools.id "
+ "JOIN identities ON leases.identity = identities.id "
+ "WHERE (? OR name = ?) "
+ "AND (? OR (identities.type = ? AND identities.data = ?)) "
+ "AND (? OR addresses.address = ?) "
+ "AND (? OR (? >= leases.acquired AND (? <= leases.released))) "
+ "AND (? OR leases.released > ? - timeout) "
+ "AND (? OR leases.released < ? - timeout) "
+ "AND ? "
+ "UNION "
+ "SELECT name, address, identities.type, identities.data, "
+ "acquired, released, timeout FROM addresses "
+ "JOIN pools ON addresses.pool = pools.id "
+ "JOIN identities ON addresses.identity = identities.id "
+ "WHERE ? AND released = 0 "
+ "AND (? OR name = ?) "
+ "AND (? OR (identities.type = ? AND identities.data = ?)) "
+ "AND (? OR address = ?)",
+ DB_INT, pool == NULL, DB_TEXT, pool,
+ DB_INT, id == NULL,
+ DB_INT, id ? id->get_type(id) : 0,
+ DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
+ DB_INT, addr == NULL,
+ DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+ DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
+ DB_INT, !valid, DB_INT, time(NULL),
+ DB_INT, !expired, DB_INT, time(NULL),
+ DB_INT, !online,
+ /* union */
+ DB_INT, !(valid || expired),
+ DB_INT, pool == NULL, DB_TEXT, pool,
+ DB_INT, id == NULL,
+ DB_INT, id ? id->get_type(id) : 0,
+ DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
+ DB_INT, addr == NULL,
+ DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+ /* res */
+ DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
+ /* id and addr leak but we can't destroy them until query is destroyed. */
+ return query;
+}
+
+/**
+ * ipsec pool --leases - show lease information of a pool
+ */
+static void leases(char *filter, bool utc)
+{
+ enumerator_t *query;
+ chunk_t address_chunk, identity_chunk;
+ int identity_type;
+ char *name;
+ u_int db_acquired, db_released, db_timeout;
+ time_t acquired, released, timeout;
+ host_t *address;
+ identification_t *identity;
+ bool found = FALSE;
+
+ query = create_lease_query(filter);
+ if (!query)
+ {
+ fprintf(stderr, "querying leases failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ while (query->enumerate(query, &name, &address_chunk, &identity_type,
+ &identity_chunk, &db_acquired, &db_released, &db_timeout))
+ {
+ if (!found)
+ {
+ int len = utc ? 25 : 21;
+
+ found = TRUE;
+ printf("%-8s %-15s %-7s %-*s %-*s %s\n",
+ "name", "address", "status", len, "start", len, "end", "identity");
+ }
+ address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
+ identity = identification_create_from_encoding(identity_type, identity_chunk);
+
+ /* u_int is not always equal to time_t */
+ acquired = (time_t)db_acquired;
+ released = (time_t)db_released;
+ timeout = (time_t)db_timeout;
+
+ printf("%-8s %-15H ", name, address);
+ if (released == 0)
+ {
+ printf("%-7s ", "online");
+ }
+ else if (timeout == 0)
+ {
+ printf("%-7s ", "static");
+ }
+ else if (released >= time(NULL) - timeout)
+ {
+ printf("%-7s ", "valid");
+ }
+ else
+ {
+ printf("%-7s ", "expired");
+ }
+
+ printf(" %T ", &acquired, utc);
+ if (released)
+ {
+ printf("%T ", &released, utc);
+ }
+ else
+ {
+ printf(" ");
+ if (utc)
+ {
+ printf(" ");
+ }
+ }
+ printf("%Y\n", identity);
+ DESTROY_IF(address);
+ identity->destroy(identity);
+ }
+ query->destroy(query);
+ if (!found)
+ {
+ fprintf(stderr, "no matching leases found.\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+/**
+ * ipsec pool --purge - delete expired leases
+ */
+static void purge(char *name)
+{
+ int purged = 0;
+
+ purged = db->execute(db, NULL,
+ "DELETE FROM leases WHERE address IN ("
+ " SELECT id FROM addresses WHERE pool IN ("
+ " SELECT id FROM pools WHERE name = ?))",
+ DB_TEXT, name);
+ if (purged < 0)
+ {
+ fprintf(stderr, "purging pool '%s' failed.\n", name);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name);
+}
+
+#define ARGV_SIZE 32
+
+static void argv_add(char **argv, int argc, char *value)
+{
+ if (argc >= ARGV_SIZE)
+ {
+ fprintf(stderr, "too many arguments: %s\n", value);
+ exit(EXIT_FAILURE);
+ }
+ argv[argc] = value;
+}
+
+/**
+ * ipsec pool --batch - read commands from a file
+ */
+static void batch(char *argv0, char *name)
+{
+ char command[512];
+
+ FILE *file = strncmp(name, "-", 1) == 0 ? stdin : fopen(name, "r");
+ if (file == NULL)
+ {
+ fprintf(stderr, "opening '%s' failed: %s\n", name, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ begin_transaction();
+ while (fgets(command, sizeof(command), file))
+ {
+ char *argv[ARGV_SIZE], *start;
+ int i, argc = 0;
+ size_t cmd_len = strlen(command);
+
+ /* ignore empty lines */
+ if (cmd_len == 1 && *(command + cmd_len - 1) == '\n')
+ {
+ continue;
+ }
+
+ /* parse command into argv */
+ start = command;
+ argv_add(argv, argc++, argv0);
+ for (i = 0; i < cmd_len; ++i)
+ {
+ if (command[i] == ' ' || command[i] == '\n')
+ {
+ if (command + i == start)
+ {
+ /* ignore leading whitespace */
+ ++start;
+ continue;
+ }
+ command[i] = '\0';
+ argv_add(argv, argc++, start);
+ start = command + i + 1;
+ }
+ }
+ if (strlen(start) > 0)
+ {
+ argv_add(argv, argc++, start);
+ }
+ argv_add(argv, argc, NULL);
+
+ do_args(argc, argv);
+ }
+ commit_transaction();
+
+ if (file != stdin)
+ {
+ fclose(file);
+ }
+}
+
+/**
+ * atexit handler to close db on shutdown
+ */
+static void cleanup(void)
+{
+ db->destroy(db);
+ DESTROY_IF(start);
+ DESTROY_IF(end);
+ DESTROY_IF(server);
+}
+
+static void do_args(int argc, char *argv[])
+{
+ char *name = "", *filter = "", *addresses = NULL;
+ int timeout = 0;
+ bool utc = FALSE;
+ enum {
+ OP_UNDEF,
+ OP_USAGE,
+ OP_STATUS,
+ OP_ADD,
+ OP_ADD_ATTR,
+ OP_DEL,
+ OP_DEL_ATTR,
+ OP_RESIZE,
+ OP_LEASES,
+ OP_PURGE,
+ OP_BATCH
+ } operation = OP_UNDEF;
+
+ /* reinit getopt state */
+ optind = 0;
+
+ while (TRUE)
+ {
+ int c;
+
+ struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+
+ { "utc", no_argument, NULL, 'u' },
+ { "status", no_argument, NULL, 'w' },
+ { "add", required_argument, NULL, 'a' },
+ { "replace", required_argument, NULL, 'c' },
+ { "del", required_argument, NULL, 'd' },
+ { "resize", required_argument, NULL, 'r' },
+ { "leases", no_argument, NULL, 'l' },
+ { "purge", required_argument, NULL, 'p' },
+ { "batch", required_argument, NULL, 'b' },
+
+ { "start", required_argument, NULL, 's' },
+ { "end", required_argument, NULL, 'e' },
+ { "addresses", required_argument, NULL, 'x' },
+ { "timeout", required_argument, NULL, 't' },
+ { "filter", required_argument, NULL, 'f' },
+ { "server", required_argument, NULL, 'v' },
+ { 0,0,0,0 }
+ };
+
+ c = getopt_long(argc, argv, "", long_opts, NULL);
+ switch (c)
+ {
+ case EOF:
+ break;
+ case 'h':
+ operation = OP_USAGE;
+ break;
+ case 'w':
+ operation = OP_STATUS;
+ break;
+ case 'u':
+ utc = TRUE;
+ continue;
+ case 'c':
+ replace_pool = TRUE;
+ /* fallthrough */
+ case 'a':
+ name = optarg;
+ operation = is_attribute(name) ? OP_ADD_ATTR : OP_ADD;
+ if (replace_pool && operation == OP_ADD_ATTR)
+ {
+ fprintf(stderr, "invalid pool name: '%s'.\n", optarg);
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'd':
+ name = optarg;
+ operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL;
+ continue;
+ case 'r':
+ name = optarg;
+ operation = OP_RESIZE;
+ continue;
+ case 'l':
+ operation = OP_LEASES;
+ continue;
+ case 'p':
+ name = optarg;
+ operation = OP_PURGE;
+ continue;
+ case 'b':
+ name = optarg;
+ if (operation == OP_BATCH)
+ {
+ fprintf(stderr, "--batch commands can not be nested\n");
+ exit(EXIT_FAILURE);
+ }
+ operation = OP_BATCH;
+ continue;
+ case 's':
+ DESTROY_IF(start);
+ start = host_create_from_string(optarg, 0);
+ if (start == NULL)
+ {
+ fprintf(stderr, "invalid start address: '%s'.\n", optarg);
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'e':
+ DESTROY_IF(end);
+ end = host_create_from_string(optarg, 0);
+ if (end == NULL)
+ {
+ fprintf(stderr, "invalid end address: '%s'.\n", optarg);
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 't':
+ timeout = atoi(optarg);
+ if (timeout == 0 && strcmp(optarg, "0") != 0)
+ {
+ fprintf(stderr, "invalid timeout '%s'.\n", optarg);
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'f':
+ filter = optarg;
+ continue;
+ case 'x':
+ addresses = optarg;
+ continue;
+ case 'v':
+ DESTROY_IF(server);
+ server = host_create_from_string(optarg, 0);
+ if (server == NULL)
+ {
+ fprintf(stderr, "invalid server address: '%s'.\n", optarg);
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
+ break;
+ }
+
+ switch (operation)
+ {
+ case OP_USAGE:
+ usage();
+ break;
+ case OP_STATUS:
+ status();
+ break;
+ case OP_ADD:
+ if (addresses != NULL)
+ {
+ add_addresses(name, addresses, timeout);
+ }
+ else if (start != NULL && end != NULL)
+ {
+ add(name, start, end, timeout);
+ }
+ else
+ {
+ fprintf(stderr, "missing arguments.\n");
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case OP_ADD_ATTR:
+ if (server == NULL)
+ {
+ fprintf(stderr, "missing arguments.\n");
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ add_attr(name, server);
+ break;
+ case OP_DEL:
+ del(name);
+ break;
+ case OP_DEL_ATTR:
+ del_attr(name, server);
+ break;
+ case OP_RESIZE:
+ if (end == NULL)
+ {
+ fprintf(stderr, "missing arguments.\n");
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ resize(name, end);
+ break;
+ case OP_LEASES:
+ leases(filter, utc);
+ break;
+ case OP_PURGE:
+ purge(name);
+ break;
+ case OP_BATCH:
+ if (name == NULL)
+ {
+ fprintf(stderr, "missing arguments.\n");
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ batch(argv[0], name);
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char *uri;
+
+ atexit(library_deinit);
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+ if (lib->integrity &&
+ !lib->integrity->check_file(lib->integrity, "pool", argv[0]))
+ {
+ fprintf(stderr, "integrity check of pool failed\n");
+ exit(SS_RC_DAEMON_INTEGRITY);
+ }
+ if (!lib->plugins->load(lib->plugins, NULL,
+ lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", NULL);
+ if (!uri)
+ {
+ fprintf(stderr, "database URI libhydra.plugins.attr-sql.database not set.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ db = lib->db->create(lib->db, uri);
+ if (!db)
+ {
+ fprintf(stderr, "opening database failed.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ atexit(cleanup);
+
+ do_args(argc, argv);
+
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c
new file mode 100644
index 000000000..a7cfde649
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/sql_attribute.c
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ */
+
+#include <time.h>
+
+#include <debug.h>
+#include <library.h>
+
+#include "sql_attribute.h"
+
+typedef struct private_sql_attribute_t private_sql_attribute_t;
+
+/**
+ * private data of sql_attribute
+ */
+struct private_sql_attribute_t {
+
+ /**
+ * public functions
+ */
+ sql_attribute_t public;
+
+ /**
+ * database connection
+ */
+ database_t *db;
+
+ /**
+ * wheter to record lease history in lease table
+ */
+ bool history;
+};
+
+/**
+ * lookup/insert an identity
+ */
+static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
+{
+ enumerator_t *e;
+ u_int row;
+
+ /* look for peer identity in the identities table */
+ e = this->db->query(this->db,
+ "SELECT id FROM identities WHERE type = ? AND data = ?",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_UINT);
+
+ if (e && e->enumerate(e, &row))
+ {
+ e->destroy(e);
+ return row;
+ }
+ DESTROY_IF(e);
+ /* not found, insert new one */
+ if (this->db->execute(this->db, &row,
+ "INSERT INTO identities (type, data) VALUES (?, ?)",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1)
+ {
+ return row;
+ }
+ return 0;
+}
+
+/**
+ * Lookup pool by name
+ */
+static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout)
+{
+ enumerator_t *e;
+ u_int pool;
+
+ e = this->db->query(this->db, "SELECT id, timeout FROM pools WHERE name = ?",
+ DB_TEXT, name, DB_UINT, DB_UINT);
+ if (e && e->enumerate(e, &pool, timeout))
+ {
+ e->destroy(e);
+ return pool;
+ }
+ DESTROY_IF(e);
+ return 0;
+}
+
+/**
+ * Look up an existing lease
+ */
+static host_t* check_lease(private_sql_attribute_t *this, char *name,
+ u_int pool, u_int identity)
+{
+ while (TRUE)
+ {
+ u_int id;
+ chunk_t address;
+ enumerator_t *e;
+ time_t now = time(NULL);
+
+ e = this->db->query(this->db,
+ "SELECT id, address FROM addresses "
+ "WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1",
+ DB_UINT, pool, DB_UINT, identity, DB_UINT, DB_BLOB);
+ if (!e || !e->enumerate(e, &id, &address))
+ {
+ DESTROY_IF(e);
+ break;
+ }
+ address = chunk_clonea(address);
+ e->destroy(e);
+
+ if (this->db->execute(this->db, NULL,
+ "UPDATE addresses SET acquired = ?, released = 0 "
+ "WHERE id = ? AND identity = ? AND released != 0",
+ DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
+ {
+ host_t *host;
+
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
+ if (host)
+ {
+ DBG1(DBG_CFG, "acquired existing lease for address %H in"
+ " pool '%s'", host, name);
+ return host;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * We check for unallocated addresses or expired leases. First we select an
+ * address as a candidate, but double check later on if it is still available
+ * during the update operation. This allows us to work without locking.
+ */
+static host_t* get_lease(private_sql_attribute_t *this, char *name,
+ u_int pool, u_int timeout, u_int identity)
+{
+ while (TRUE)
+ {
+ u_int id;
+ chunk_t address;
+ enumerator_t *e;
+ time_t now = time(NULL);
+ int hits;
+
+ if (timeout)
+ {
+ /* check for an expired lease */
+ e = this->db->query(this->db,
+ "SELECT id, address FROM addresses "
+ "WHERE pool = ? AND released != 0 AND released < ? LIMIT 1",
+ DB_UINT, pool, DB_UINT, now - timeout, DB_UINT, DB_BLOB);
+ }
+ else
+ {
+ /* with static leases, check for an unallocated address */
+ e = this->db->query(this->db,
+ "SELECT id, address FROM addresses "
+ "WHERE pool = ? AND identity = 0 LIMIT 1",
+ DB_UINT, pool, DB_UINT, DB_BLOB);
+
+ }
+
+ if (!e || !e->enumerate(e, &id, &address))
+ {
+ DESTROY_IF(e);
+ break;
+ }
+ address = chunk_clonea(address);
+ e->destroy(e);
+
+ if (timeout)
+ {
+ hits = this->db->execute(this->db, NULL,
+ "UPDATE addresses SET "
+ "acquired = ?, released = 0, identity = ? "
+ "WHERE id = ? AND released != 0 AND released < ?",
+ DB_UINT, now, DB_UINT, identity,
+ DB_UINT, id, DB_UINT, now - timeout);
+ }
+ else
+ {
+ hits = this->db->execute(this->db, NULL,
+ "UPDATE addresses SET "
+ "acquired = ?, released = 0, identity = ? "
+ "WHERE id = ? AND identity = 0",
+ DB_UINT, now, DB_UINT, identity, DB_UINT, id);
+ }
+ if (hits > 0)
+ {
+ host_t *host;
+
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
+ if (host)
+ {
+ DBG1(DBG_CFG, "acquired new lease for address %H in pool '%s'",
+ host, name);
+ return host;
+ }
+ }
+ }
+ DBG1(DBG_CFG, "no available address found in pool '%s'", name);
+ return NULL;
+}
+
+/**
+ * Implementation of attribute_provider_t.acquire_address
+ */
+static host_t* acquire_address(private_sql_attribute_t *this,
+ char *names, identification_t *id,
+ host_t *requested)
+{
+ host_t *address = NULL;
+ u_int identity, pool, timeout;
+
+ identity = get_identity(this, id);
+ if (identity)
+ {
+ /* check for a single pool first (no concatenation and enumeration) */
+ if (strchr(names, ',') == NULL)
+ {
+ pool = get_pool(this, names, &timeout);
+ if (pool)
+ {
+ /* check for an existing lease */
+ address = check_lease(this, names, pool, identity);
+ if (address == NULL)
+ {
+ /* get an unallocated address or expired lease */
+ address = get_lease(this, names, pool, timeout, identity);
+ }
+ }
+ }
+ else
+ {
+ enumerator_t *enumerator;
+ char *name;
+
+ /* in a first step check for an existing lease over all pools */
+ enumerator = enumerator_create_token(names, ",", " ");
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = get_pool(this, name, &timeout);
+ if (pool)
+ {
+ address = check_lease(this, name, pool, identity);
+ if (address)
+ {
+ enumerator->destroy(enumerator);
+ return address;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* in a second step get an unallocated address or expired lease */
+ enumerator = enumerator_create_token(names, ",", " ");
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = get_pool(this, name, &timeout);
+ if (pool)
+ {
+ address = get_lease(this, name, pool, timeout, identity);
+ if (address)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ return address;
+}
+
+/**
+ * Implementation of attribute_provider_t.release_address
+ */
+static bool release_address(private_sql_attribute_t *this,
+ char *name, host_t *address, identification_t *id)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ time_t now = time(NULL);
+
+ enumerator = enumerator_create_token(name, ",", " ");
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ u_int pool, timeout;
+
+ pool = get_pool(this, name, &timeout);
+ if (pool)
+ {
+ if (this->history)
+ {
+ this->db->execute(this->db, NULL,
+ "INSERT INTO leases (address, identity, acquired, released)"
+ " SELECT id, identity, acquired, ? FROM addresses "
+ " WHERE pool = ? AND address = ?",
+ DB_UINT, now, DB_UINT, pool,
+ DB_BLOB, address->get_address(address));
+ }
+ if (this->db->execute(this->db, NULL,
+ "UPDATE addresses SET released = ? WHERE "
+ "pool = ? AND address = ?", DB_UINT, time(NULL),
+ DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Implementation of sql_attribute_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_sql_attribute_t *this,
+ identification_t *id, host_t *vip)
+{
+ if (vip)
+ {
+ enumerator_t *enumerator;
+
+ enumerator = this->db->query(this->db,
+ "SELECT type, value FROM attributes", DB_INT, DB_BLOB);
+ if (enumerator)
+ {
+ return enumerator;
+ }
+ }
+ return enumerator_create_empty();
+}
+
+/**
+ * Implementation of sql_attribute_t.destroy
+ */
+static void destroy(private_sql_attribute_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+sql_attribute_t *sql_attribute_create(database_t *db)
+{
+ private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t);
+ time_t now = time(NULL);
+
+ this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
+ this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
+ this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *host))create_attribute_enumerator;
+ this->public.destroy = (void(*)(sql_attribute_t*))destroy;
+
+ this->db = db;
+ this->history = lib->settings->get_bool(lib->settings,
+ "libhydra.plugins.attr-sql.lease_history", TRUE);
+
+ /* close any "online" leases in the case we crashed */
+ if (this->history)
+ {
+ this->db->execute(this->db, NULL,
+ "INSERT INTO leases (address, identity, acquired, released)"
+ " SELECT id, identity, acquired, ? FROM addresses "
+ " WHERE released = 0", DB_UINT, now);
+ }
+ this->db->execute(this->db, NULL,
+ "UPDATE addresses SET released = ? WHERE released = 0",
+ DB_UINT, now);
+ return &this->public;
+}
+
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.h b/src/libhydra/plugins/attr_sql/sql_attribute.h
new file mode 100644
index 000000000..ca87eb27e
--- /dev/null
+++ b/src/libhydra/plugins/attr_sql/sql_attribute.h
@@ -0,0 +1,50 @@
+/*
+ * 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 sql_attribute sql_attribute
+ * @{ @ingroup attr_sql
+ */
+
+#ifndef SQL_ATTRIBUTE_H_
+#define SQL_ATTRIBUTE_H_
+
+#include <attributes/attribute_provider.h>
+#include <database/database.h>
+
+typedef struct sql_attribute_t sql_attribute_t;
+
+/**
+ * SQL database based IKEv2 cfg attribute provider.
+ */
+struct sql_attribute_t {
+
+ /**
+ * Implements attribute provider interface
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Destroy a sql_attribute instance.
+ */
+ void (*destroy)(sql_attribute_t *this);
+};
+
+/**
+ * Create a sql_attribute instance.
+ */
+sql_attribute_t *sql_attribute_create(database_t *db);
+
+#endif /** SQL_ATTRIBUTE_H_ @}*/
diff --git a/src/libsimaka/Makefile.am b/src/libsimaka/Makefile.am
index f64e4dba3..8e7a1f0d3 100644
--- a/src/libsimaka/Makefile.am
+++ b/src/libsimaka/Makefile.am
@@ -1,5 +1,5 @@
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
noinst_LTLIBRARIES = libsimaka.la
libsimaka_la_SOURCES = simaka_message.h simaka_message.c \
diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in
index 9a448ef02..ab07cb214 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libsimaka/Makefile.in
@@ -192,6 +192,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -226,7 +227,7 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
noinst_LTLIBRARIES = libsimaka.la
libsimaka_la_SOURCES = simaka_message.h simaka_message.c \
simaka_crypto.h simaka_crypto.c
diff --git a/src/libsimaka/simaka_message.c b/src/libsimaka/simaka_message.c
index 22d111bfd..e0319e918 100644
--- a/src/libsimaka/simaka_message.c
+++ b/src/libsimaka/simaka_message.c
@@ -256,16 +256,12 @@ static void add_attribute(private_simaka_message_t *this,
{
attr_t *attr;
- if (!charon->sim->attribute_hook(charon->sim, this->hdr->code,
- this->hdr->type, this->hdr->subtype, type, data))
- {
- attr = malloc(sizeof(attr_t) + data.len);
- attr->len = data.len;
- attr->type = type;
- memcpy(attr->data, data.ptr, data.len);
+ attr = malloc(sizeof(attr_t) + data.len);
+ attr->len = data.len;
+ attr->type = type;
+ memcpy(attr->data, data.ptr, data.len);
- this->attributes->insert_last(this->attributes, attr);
- }
+ this->attributes->insert_last(this->attributes, attr);
}
/**
@@ -463,6 +459,9 @@ static bool parse_attributes(private_simaka_message_t *this, chunk_t in)
break;
}
}
+
+ charon->sim->message_hook(charon->sim, &this->public, TRUE, this->encrypted);
+
return TRUE;
}
@@ -604,6 +603,8 @@ static eap_payload_t* generate(private_simaka_message_t *this, chunk_t sigdata)
u_int16_t len;
signer_t *signer;
+ charon->sim->message_hook(charon->sim, &this->public, FALSE, TRUE);
+
out = chunk_create(out_buf, sizeof(out_buf));
encr = chunk_create(encr_buf, sizeof(encr_buf));
@@ -814,6 +815,9 @@ static eap_payload_t* generate(private_simaka_message_t *this, chunk_t sigdata)
data = chunk_cata("cc", out, sigdata);
signer->get_signature(signer, data, mac.ptr);
}
+
+ charon->sim->message_hook(charon->sim, &this->public, FALSE, FALSE);
+
return eap_payload_create_data(out);
}
diff --git a/src/libsimaka/simaka_message.h b/src/libsimaka/simaka_message.h
index ee9b3ebec..341f72959 100644
--- a/src/libsimaka/simaka_message.h
+++ b/src/libsimaka/simaka_message.h
@@ -31,7 +31,6 @@
#include "simaka_crypto.h"
-typedef struct simaka_message_t simaka_message_t;
typedef enum simaka_attribute_t simaka_attribute_t;
typedef enum simaka_subtype_t simaka_subtype_t;
typedef enum simaka_notification_t simaka_notification_t;
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
new file mode 100644
index 000000000..d639220e3
--- /dev/null
+++ b/src/libstrongswan/Android.mk
@@ -0,0 +1,121 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+library.c library.h \
+chunk.c chunk.h \
+debug.c debug.h \
+enum.c enum.h \
+settings.h settings.c \
+printf_hook.c printf_hook.h \
+asn1/asn1.c asn1/asn1.h \
+asn1/asn1_parser.c asn1/asn1_parser.h \
+asn1/oid.c asn1/oid.h \
+crypto/crypters/crypter.c crypto/crypters/crypter.h \
+crypto/hashers/hasher.h crypto/hashers/hasher.c \
+crypto/pkcs9.c crypto/pkcs9.h \
+crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords.h \
+crypto/prfs/prf.c crypto/prfs/prf.h \
+crypto/rngs/rng.c crypto/rngs/rng.h \
+crypto/prf_plus.h crypto/prf_plus.c \
+crypto/signers/signer.c crypto/signers/signer.h \
+crypto/crypto_factory.c crypto/crypto_factory.h \
+crypto/crypto_tester.c crypto/crypto_tester.h \
+crypto/diffie_hellman.c crypto/diffie_hellman.h \
+crypto/transform.c crypto/transform.h \
+credentials/credential_factory.c credentials/credential_factory.h \
+credentials/builder.c credentials/builder.h \
+credentials/keys/key_encoding.c credentials/keys/key_encoding.h \
+credentials/keys/private_key.c credentials/keys/private_key.h \
+credentials/keys/public_key.c credentials/keys/public_key.h \
+credentials/keys/shared_key.c credentials/keys/shared_key.h \
+credentials/certificates/certificate.c credentials/certificates/certificate.h \
+credentials/certificates/x509.h credentials/certificates/x509.c \
+credentials/certificates/ac.h \
+credentials/certificates/crl.h credentials/certificates/crl.c \
+credentials/certificates/pkcs10.h \
+credentials/certificates/ocsp_request.h \
+credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
+credentials/certificates/pgp_certificate.h \
+credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
+database/database.h database/database_factory.h database/database_factory.c \
+fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
+selectors/traffic_selector.c selectors/traffic_selector.h \
+threading/thread.h threading/thread.c \
+threading/thread_value.h threading/thread_value.c \
+threading/mutex.h threading/mutex.c threading/condvar.h \
+threading/rwlock.h threading/rwlock.c \
+threading/lock_profiler.h \
+utils.h utils.c \
+utils/host.c utils/host.h \
+utils/identification.c utils/identification.h \
+utils/iterator.h \
+utils/lexparser.c utils/lexparser.h \
+utils/linked_list.c utils/linked_list.h \
+utils/hashtable.c utils/hashtable.h \
+utils/enumerator.c utils/enumerator.h \
+utils/optionsfrom.c utils/optionsfrom.h \
+utils/backtrace.c utils/backtrace.h \
+plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h
+
+# adding the plugin source files
+
+LOCAL_SRC_FILES += $(call add_plugin, aes)
+
+LOCAL_SRC_FILES += $(call add_plugin, des)
+
+LOCAL_SRC_FILES += $(call add_plugin, fips-prf)
+
+LOCAL_SRC_FILES += $(call add_plugin, gmp)
+ifneq ($(call plugin_enabled, gmp)),)
+LOCAL_C_INCLUDES += $(libgmp_PATH)
+LOCAL_SHARED_LIBRARIES += libgmp
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, hmac)
+
+LOCAL_SRC_FILES += $(call add_plugin, md4)
+
+LOCAL_SRC_FILES += $(call add_plugin, md5)
+
+LOCAL_SRC_FILES += $(call add_plugin, openssl)
+ifneq ($(call plugin_enabled, openssl)),)
+LOCAL_C_INCLUDES += external/openssl/include
+LOCAL_SHARED_LIBRARIES += libcrypto
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, pem)
+
+LOCAL_SRC_FILES += $(call add_plugin, pkcs1)
+
+LOCAL_SRC_FILES += $(call add_plugin, pubkey)
+
+LOCAL_SRC_FILES += $(call add_plugin, random)
+
+LOCAL_SRC_FILES += $(call add_plugin, sha1)
+
+LOCAL_SRC_FILES += $(call add_plugin, sha2)
+
+LOCAL_SRC_FILES += $(call add_plugin, x509)
+
+LOCAL_SRC_FILES += $(call add_plugin, xcbc)
+
+# build libstrongswan ----------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH)
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
+ -include $(LOCAL_PATH)/AndroidConfigLocal.h
+
+LOCAL_MODULE := libstrongswan
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libdl libvstr
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/src/libstrongswan/AndroidConfigLocal.h b/src/libstrongswan/AndroidConfigLocal.h
new file mode 100644
index 000000000..a6da3276a
--- /dev/null
+++ b/src/libstrongswan/AndroidConfigLocal.h
@@ -0,0 +1,9 @@
+/* stuff defined in AndroidConfig.h, which is included using the -include
+ * command-line option, thus cannot be undefined using -U CFLAGS options.
+ * the reason we have to undefine these flags in the first place, is that
+ * AndroidConfig.h defines them as 0, which in turn means that they are
+ * actually defined. */
+
+#undef HAVE_BACKTRACE
+#undef HAVE_DLADDR
+
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 7ee15052c..157d37b5e 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -10,9 +10,6 @@ printf_hook.c printf_hook.h \
asn1/asn1.c asn1/asn1.h \
asn1/asn1_parser.c asn1/asn1_parser.h \
asn1/oid.c asn1/oid.h \
-attributes/attributes.c attributes/attributes.h \
-attributes/attribute_provider.h attributes/attribute_handler.h \
-attributes/attribute_manager.c attributes/attribute_manager.h \
crypto/crypters/crypter.c crypto/crypters/crypter.h \
crypto/hashers/hasher.h crypto/hashers/hasher.c \
crypto/pkcs9.c crypto/pkcs9.h \
@@ -90,7 +87,8 @@ endif
EXTRA_DIST = \
asn1/oid.txt asn1/oid.pl \
-crypto/proposal/proposal_keywords.txt
+crypto/proposal/proposal_keywords.txt \
+Android.mk AndroidConfigLocal.h
BUILT_SOURCES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
@@ -115,116 +113,197 @@ $(srcdir)/crypto/proposal/proposal_keywords.c: $(srcdir)/crypto/proposal/proposa
# build plugins with their own Makefile
#######################################
+if MONOLITHIC
+SUBDIRS =
+else
SUBDIRS = .
+endif
if USE_AES
SUBDIRS += plugins/aes
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/aes/libstrongswan-aes.la
+endif
endif
if USE_DES
SUBDIRS += plugins/des
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/des/libstrongswan-des.la
+endif
endif
if USE_BLOWFISH
SUBDIRS += plugins/blowfish
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/blowfish/libstrongswan-blowfish.la
+endif
endif
if USE_MD4
SUBDIRS += plugins/md4
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/md4/libstrongswan-md4.la
+endif
endif
if USE_MD5
SUBDIRS += plugins/md5
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/md5/libstrongswan-md5.la
+endif
endif
if USE_SHA1
SUBDIRS += plugins/sha1
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/sha1/libstrongswan-sha1.la
+endif
endif
if USE_SHA2
SUBDIRS += plugins/sha2
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/sha2/libstrongswan-sha2.la
endif
-
-if USE_FIPS_PRF
- SUBDIRS += plugins/fips_prf
endif
if USE_GMP
SUBDIRS += plugins/gmp
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/gmp/libstrongswan-gmp.la
+endif
endif
if USE_RANDOM
SUBDIRS += plugins/random
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/random/libstrongswan-random.la
+endif
endif
if USE_HMAC
SUBDIRS += plugins/hmac
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/hmac/libstrongswan-hmac.la
+endif
endif
if USE_XCBC
SUBDIRS += plugins/xcbc
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/xcbc/libstrongswan-xcbc.la
+endif
endif
if USE_X509
SUBDIRS += plugins/x509
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/x509/libstrongswan-x509.la
+endif
endif
if USE_PUBKEY
SUBDIRS += plugins/pubkey
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/pubkey/libstrongswan-pubkey.la
+endif
endif
if USE_PKCS1
SUBDIRS += plugins/pkcs1
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/pkcs1/libstrongswan-pkcs1.la
+endif
endif
if USE_PGP
SUBDIRS += plugins/pgp
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/pgp/libstrongswan-pgp.la
+endif
endif
if USE_DNSKEY
SUBDIRS += plugins/dnskey
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/dnskey/libstrongswan-dnskey.la
+endif
endif
if USE_PEM
SUBDIRS += plugins/pem
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/pem/libstrongswan-pem.la
+endif
endif
if USE_CURL
SUBDIRS += plugins/curl
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/curl/libstrongswan-curl.la
+endif
endif
if USE_LDAP
SUBDIRS += plugins/ldap
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/ldap/libstrongswan-ldap.la
+endif
endif
if USE_MYSQL
SUBDIRS += plugins/mysql
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/mysql/libstrongswan-mysql.la
+endif
endif
if USE_SQLITE
SUBDIRS += plugins/sqlite
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/sqlite/libstrongswan-sqlite.la
endif
-
-if USE_ATTR_SQL
- SUBDIRS += plugins/attr_sql
endif
if USE_PADLOCK
SUBDIRS += plugins/padlock
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/padlock/libstrongswan-padlock.la
+endif
endif
if USE_OPENSSL
SUBDIRS += plugins/openssl
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/openssl/libstrongswan-openssl.la
+endif
endif
if USE_GCRYPT
SUBDIRS += plugins/gcrypt
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/gcrypt/libstrongswan-gcrypt.la
+endif
+endif
+
+if USE_FIPS_PRF
+ SUBDIRS += plugins/fips_prf
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/fips_prf/libstrongswan-fips-prf.la
+endif
endif
if USE_AGENT
SUBDIRS += plugins/agent
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/agent/libstrongswan-agent.la
+endif
endif
if USE_TEST_VECTORS
SUBDIRS += plugins/test_vectors
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/test_vectors/libstrongswan-test-vectors.la
+endif
endif
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 729d32eb3..b8d967d4a 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -45,33 +45,59 @@ host_triplet = @host@
@USE_VSTR_TRUE@am__append_6 = -lvstr
@USE_AES_TRUE@am__append_7 = plugins/aes
-@USE_DES_TRUE@am__append_8 = plugins/des
-@USE_BLOWFISH_TRUE@am__append_9 = plugins/blowfish
-@USE_MD4_TRUE@am__append_10 = plugins/md4
-@USE_MD5_TRUE@am__append_11 = plugins/md5
-@USE_SHA1_TRUE@am__append_12 = plugins/sha1
-@USE_SHA2_TRUE@am__append_13 = plugins/sha2
-@USE_FIPS_PRF_TRUE@am__append_14 = plugins/fips_prf
-@USE_GMP_TRUE@am__append_15 = plugins/gmp
-@USE_RANDOM_TRUE@am__append_16 = plugins/random
-@USE_HMAC_TRUE@am__append_17 = plugins/hmac
-@USE_XCBC_TRUE@am__append_18 = plugins/xcbc
-@USE_X509_TRUE@am__append_19 = plugins/x509
-@USE_PUBKEY_TRUE@am__append_20 = plugins/pubkey
-@USE_PKCS1_TRUE@am__append_21 = plugins/pkcs1
-@USE_PGP_TRUE@am__append_22 = plugins/pgp
-@USE_DNSKEY_TRUE@am__append_23 = plugins/dnskey
-@USE_PEM_TRUE@am__append_24 = plugins/pem
-@USE_CURL_TRUE@am__append_25 = plugins/curl
-@USE_LDAP_TRUE@am__append_26 = plugins/ldap
-@USE_MYSQL_TRUE@am__append_27 = plugins/mysql
-@USE_SQLITE_TRUE@am__append_28 = plugins/sqlite
-@USE_ATTR_SQL_TRUE@am__append_29 = plugins/attr_sql
-@USE_PADLOCK_TRUE@am__append_30 = plugins/padlock
-@USE_OPENSSL_TRUE@am__append_31 = plugins/openssl
-@USE_GCRYPT_TRUE@am__append_32 = plugins/gcrypt
-@USE_AGENT_TRUE@am__append_33 = plugins/agent
-@USE_TEST_VECTORS_TRUE@am__append_34 = plugins/test_vectors
+@MONOLITHIC_TRUE@@USE_AES_TRUE@am__append_8 = plugins/aes/libstrongswan-aes.la
+@USE_DES_TRUE@am__append_9 = plugins/des
+@MONOLITHIC_TRUE@@USE_DES_TRUE@am__append_10 = plugins/des/libstrongswan-des.la
+@USE_BLOWFISH_TRUE@am__append_11 = plugins/blowfish
+@MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE@am__append_12 = plugins/blowfish/libstrongswan-blowfish.la
+@USE_MD4_TRUE@am__append_13 = plugins/md4
+@MONOLITHIC_TRUE@@USE_MD4_TRUE@am__append_14 = plugins/md4/libstrongswan-md4.la
+@USE_MD5_TRUE@am__append_15 = plugins/md5
+@MONOLITHIC_TRUE@@USE_MD5_TRUE@am__append_16 = plugins/md5/libstrongswan-md5.la
+@USE_SHA1_TRUE@am__append_17 = plugins/sha1
+@MONOLITHIC_TRUE@@USE_SHA1_TRUE@am__append_18 = plugins/sha1/libstrongswan-sha1.la
+@USE_SHA2_TRUE@am__append_19 = plugins/sha2
+@MONOLITHIC_TRUE@@USE_SHA2_TRUE@am__append_20 = plugins/sha2/libstrongswan-sha2.la
+@USE_GMP_TRUE@am__append_21 = plugins/gmp
+@MONOLITHIC_TRUE@@USE_GMP_TRUE@am__append_22 = plugins/gmp/libstrongswan-gmp.la
+@USE_RANDOM_TRUE@am__append_23 = plugins/random
+@MONOLITHIC_TRUE@@USE_RANDOM_TRUE@am__append_24 = plugins/random/libstrongswan-random.la
+@USE_HMAC_TRUE@am__append_25 = plugins/hmac
+@MONOLITHIC_TRUE@@USE_HMAC_TRUE@am__append_26 = plugins/hmac/libstrongswan-hmac.la
+@USE_XCBC_TRUE@am__append_27 = plugins/xcbc
+@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_28 = plugins/xcbc/libstrongswan-xcbc.la
+@USE_X509_TRUE@am__append_29 = plugins/x509
+@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_30 = plugins/x509/libstrongswan-x509.la
+@USE_PUBKEY_TRUE@am__append_31 = plugins/pubkey
+@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_32 = plugins/pubkey/libstrongswan-pubkey.la
+@USE_PKCS1_TRUE@am__append_33 = plugins/pkcs1
+@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_34 = plugins/pkcs1/libstrongswan-pkcs1.la
+@USE_PGP_TRUE@am__append_35 = plugins/pgp
+@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_36 = plugins/pgp/libstrongswan-pgp.la
+@USE_DNSKEY_TRUE@am__append_37 = plugins/dnskey
+@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_38 = plugins/dnskey/libstrongswan-dnskey.la
+@USE_PEM_TRUE@am__append_39 = plugins/pem
+@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_40 = plugins/pem/libstrongswan-pem.la
+@USE_CURL_TRUE@am__append_41 = plugins/curl
+@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_42 = plugins/curl/libstrongswan-curl.la
+@USE_LDAP_TRUE@am__append_43 = plugins/ldap
+@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_44 = plugins/ldap/libstrongswan-ldap.la
+@USE_MYSQL_TRUE@am__append_45 = plugins/mysql
+@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_46 = plugins/mysql/libstrongswan-mysql.la
+@USE_SQLITE_TRUE@am__append_47 = plugins/sqlite
+@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_48 = plugins/sqlite/libstrongswan-sqlite.la
+@USE_PADLOCK_TRUE@am__append_49 = plugins/padlock
+@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_50 = plugins/padlock/libstrongswan-padlock.la
+@USE_OPENSSL_TRUE@am__append_51 = plugins/openssl
+@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_52 = plugins/openssl/libstrongswan-openssl.la
+@USE_GCRYPT_TRUE@am__append_53 = plugins/gcrypt
+@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_54 = plugins/gcrypt/libstrongswan-gcrypt.la
+@USE_FIPS_PRF_TRUE@am__append_55 = plugins/fips_prf
+@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_56 = plugins/fips_prf/libstrongswan-fips-prf.la
+@USE_AGENT_TRUE@am__append_57 = plugins/agent
+@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_58 = plugins/agent/libstrongswan-agent.la
+@USE_TEST_VECTORS_TRUE@am__append_59 = plugins/test_vectors
+@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_60 = plugins/test_vectors/libstrongswan-test-vectors.la
subdir = src/libstrongswan
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -115,14 +141,20 @@ 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__append_8) $(am__append_10) \
+ $(am__append_12) $(am__append_14) $(am__append_16) \
+ $(am__append_18) $(am__append_20) $(am__append_22) \
+ $(am__append_24) $(am__append_26) $(am__append_28) \
+ $(am__append_30) $(am__append_32) $(am__append_34) \
+ $(am__append_36) $(am__append_38) $(am__append_40) \
+ $(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__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
chunk.h debug.c debug.h enum.c enum.h settings.h settings.c \
printf_hook.c printf_hook.h asn1/asn1.c asn1/asn1.h \
asn1/asn1_parser.c asn1/asn1_parser.h asn1/oid.c asn1/oid.h \
- attributes/attributes.c attributes/attributes.h \
- attributes/attribute_provider.h attributes/attribute_handler.h \
- attributes/attribute_manager.c attributes/attribute_manager.h \
crypto/crypters/crypter.c crypto/crypters/crypter.h \
crypto/hashers/hasher.h crypto/hashers/hasher.c crypto/pkcs9.c \
crypto/pkcs9.h crypto/proposal/proposal_keywords.c \
@@ -173,10 +205,10 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
@USE_INTEGRITY_TEST_TRUE@am__objects_2 = integrity_checker.lo
am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \
settings.lo printf_hook.lo asn1.lo asn1_parser.lo oid.lo \
- attributes.lo attribute_manager.lo crypter.lo hasher.lo \
- pkcs9.lo proposal_keywords.lo prf.lo rng.lo prf_plus.lo \
- signer.lo crypto_factory.lo crypto_tester.lo diffie_hellman.lo \
- transform.lo credential_factory.lo builder.lo key_encoding.lo \
+ crypter.lo hasher.lo pkcs9.lo proposal_keywords.lo prf.lo \
+ rng.lo prf_plus.lo signer.lo crypto_factory.lo \
+ crypto_tester.lo diffie_hellman.lo transform.lo \
+ credential_factory.lo builder.lo key_encoding.lo \
private_key.lo public_key.lo shared_key.lo certificate.lo \
x509.lo crl.lo ocsp_response.lo ietf_attributes.lo \
database_factory.lo fetcher_manager.lo traffic_selector.lo \
@@ -215,13 +247,12 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = . plugins/aes plugins/des plugins/blowfish plugins/md4 \
- plugins/md5 plugins/sha1 plugins/sha2 plugins/fips_prf \
- plugins/gmp plugins/random plugins/hmac plugins/xcbc \
- plugins/x509 plugins/pubkey plugins/pkcs1 plugins/pgp \
- plugins/dnskey plugins/pem plugins/curl plugins/ldap \
- plugins/mysql plugins/sqlite plugins/attr_sql plugins/padlock \
- plugins/openssl plugins/gcrypt plugins/agent \
- plugins/test_vectors
+ plugins/md5 plugins/sha1 plugins/sha2 plugins/gmp \
+ plugins/random plugins/hmac plugins/xcbc plugins/x509 \
+ plugins/pubkey plugins/pkcs1 plugins/pgp plugins/dnskey \
+ plugins/pem plugins/curl plugins/ldap plugins/mysql \
+ plugins/sqlite plugins/padlock plugins/openssl plugins/gcrypt \
+ plugins/fips_prf plugins/agent plugins/test_vectors
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -368,6 +399,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -407,9 +439,6 @@ libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \
debug.h enum.c enum.h settings.h settings.c printf_hook.c \
printf_hook.h asn1/asn1.c asn1/asn1.h asn1/asn1_parser.c \
asn1/asn1_parser.h asn1/oid.c asn1/oid.h \
- attributes/attributes.c attributes/attributes.h \
- attributes/attribute_provider.h attributes/attribute_handler.h \
- attributes/attribute_manager.c attributes/attribute_manager.h \
crypto/crypters/crypter.c crypto/crypters/crypter.h \
crypto/hashers/hasher.h crypto/hashers/hasher.c crypto/pkcs9.c \
crypto/pkcs9.h crypto/proposal/proposal_keywords.c \
@@ -456,14 +485,24 @@ libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \
plugins/plugin_loader.h plugins/plugin.h $(am__append_2) \
$(am__append_5)
libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) \
- $(RTLIB) $(am__append_6)
+ $(RTLIB) $(am__append_6) $(am__append_8) $(am__append_10) \
+ $(am__append_12) $(am__append_14) $(am__append_16) \
+ $(am__append_18) $(am__append_20) $(am__append_22) \
+ $(am__append_24) $(am__append_26) $(am__append_28) \
+ $(am__append_30) $(am__append_32) $(am__append_34) \
+ $(am__append_36) $(am__append_38) $(am__append_40) \
+ $(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)
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DPLUGINDIR=\"${plugindir}\" \
-DSTRONGSWAN_CONF=\"${strongswan_conf}\" $(am__append_1) \
$(am__append_3) $(am__append_4)
EXTRA_DIST = \
asn1/oid.txt asn1/oid.pl \
-crypto/proposal/proposal_keywords.txt
+crypto/proposal/proposal_keywords.txt \
+Android.mk AndroidConfigLocal.h
BUILT_SOURCES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
@@ -473,19 +512,37 @@ MAINTAINERCLEANFILES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
$(srcdir)/crypto/proposal/proposal_keywords.c
+@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_7) $(am__append_9) \
+@MONOLITHIC_FALSE@ $(am__append_11) $(am__append_13) \
+@MONOLITHIC_FALSE@ $(am__append_15) $(am__append_17) \
+@MONOLITHIC_FALSE@ $(am__append_19) $(am__append_21) \
+@MONOLITHIC_FALSE@ $(am__append_23) $(am__append_25) \
+@MONOLITHIC_FALSE@ $(am__append_27) $(am__append_29) \
+@MONOLITHIC_FALSE@ $(am__append_31) $(am__append_33) \
+@MONOLITHIC_FALSE@ $(am__append_35) $(am__append_37) \
+@MONOLITHIC_FALSE@ $(am__append_39) $(am__append_41) \
+@MONOLITHIC_FALSE@ $(am__append_43) $(am__append_45) \
+@MONOLITHIC_FALSE@ $(am__append_47) $(am__append_49) \
+@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_53) \
+@MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \
+@MONOLITHIC_FALSE@ $(am__append_59)
# build plugins with their own Makefile
#######################################
-SUBDIRS = . $(am__append_7) $(am__append_8) $(am__append_9) \
- $(am__append_10) $(am__append_11) $(am__append_12) \
- $(am__append_13) $(am__append_14) $(am__append_15) \
- $(am__append_16) $(am__append_17) $(am__append_18) \
- $(am__append_19) $(am__append_20) $(am__append_21) \
- $(am__append_22) $(am__append_23) $(am__append_24) \
- $(am__append_25) $(am__append_26) $(am__append_27) \
- $(am__append_28) $(am__append_29) $(am__append_30) \
- $(am__append_31) $(am__append_32) $(am__append_33) \
- $(am__append_34)
+@MONOLITHIC_TRUE@SUBDIRS = $(am__append_7) $(am__append_9) \
+@MONOLITHIC_TRUE@ $(am__append_11) $(am__append_13) \
+@MONOLITHIC_TRUE@ $(am__append_15) $(am__append_17) \
+@MONOLITHIC_TRUE@ $(am__append_19) $(am__append_21) \
+@MONOLITHIC_TRUE@ $(am__append_23) $(am__append_25) \
+@MONOLITHIC_TRUE@ $(am__append_27) $(am__append_29) \
+@MONOLITHIC_TRUE@ $(am__append_31) $(am__append_33) \
+@MONOLITHIC_TRUE@ $(am__append_35) $(am__append_37) \
+@MONOLITHIC_TRUE@ $(am__append_39) $(am__append_41) \
+@MONOLITHIC_TRUE@ $(am__append_43) $(am__append_45) \
+@MONOLITHIC_TRUE@ $(am__append_47) $(am__append_49) \
+@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_53) \
+@MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \
+@MONOLITHIC_TRUE@ $(am__append_59)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -563,8 +620,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1_parser.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attribute_manager.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attributes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certificate.Plo@am__quote@
@@ -657,20 +712,6 @@ oid.lo: asn1/oid.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o oid.lo `test -f 'asn1/oid.c' || echo '$(srcdir)/'`asn1/oid.c
-attributes.lo: attributes/attributes.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attributes.lo -MD -MP -MF $(DEPDIR)/attributes.Tpo -c -o attributes.lo `test -f 'attributes/attributes.c' || echo '$(srcdir)/'`attributes/attributes.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/attributes.Tpo $(DEPDIR)/attributes.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attributes/attributes.c' object='attributes.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attributes.lo `test -f 'attributes/attributes.c' || echo '$(srcdir)/'`attributes/attributes.c
-
-attribute_manager.lo: attributes/attribute_manager.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attribute_manager.lo -MD -MP -MF $(DEPDIR)/attribute_manager.Tpo -c -o attribute_manager.lo `test -f 'attributes/attribute_manager.c' || echo '$(srcdir)/'`attributes/attribute_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/attribute_manager.Tpo $(DEPDIR)/attribute_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attributes/attribute_manager.c' object='attribute_manager.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attribute_manager.lo `test -f 'attributes/attribute_manager.c' || echo '$(srcdir)/'`attributes/attribute_manager.c
-
crypter.lo: crypto/crypters/crypter.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crypter.lo -MD -MP -MF $(DEPDIR)/crypter.Tpo -c -o crypter.lo `test -f 'crypto/crypters/crypter.c' || echo '$(srcdir)/'`crypto/crypters/crypter.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/crypter.Tpo $(DEPDIR)/crypter.Plo
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 763caafc4..6264bdc54 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -19,7 +19,6 @@
#include <string.h>
#include <time.h>
-#include <utils.h>
#include <debug.h>
#include "oid.h"
@@ -134,7 +133,7 @@ size_t asn1_length(chunk_t *blob)
if (blob->len < 2)
{
- DBG2("insufficient number of octets to parse ASN.1 length");
+ DBG2(DBG_LIB, "insufficient number of octets to parse ASN.1 length");
return ASN1_INVALID_LENGTH;
}
@@ -146,7 +145,7 @@ size_t asn1_length(chunk_t *blob)
{ /* single length octet */
if (n > blob->len)
{
- DBG2("length is larger than remaining blob size");
+ DBG2(DBG_LIB, "length is larger than remaining blob size");
return ASN1_INVALID_LENGTH;
}
return n;
@@ -157,14 +156,14 @@ size_t asn1_length(chunk_t *blob)
if (n == 0 || n > blob->len)
{
- DBG2("number of length octets invalid");
+ DBG2(DBG_LIB, "number of length octets invalid");
return ASN1_INVALID_LENGTH;
}
if (n > sizeof(len))
{
- DBG2("number of length octets is larger than limit of %d octets",
- (int)sizeof(len));
+ DBG2(DBG_LIB, "number of length octets is larger than limit of"
+ " %d octets", (int)sizeof(len));
return ASN1_INVALID_LENGTH;
}
@@ -177,7 +176,7 @@ size_t asn1_length(chunk_t *blob)
}
if (len > blob->len)
{
- DBG2("length is larger than remaining blob size");
+ DBG2(DBG_LIB, "length is larger than remaining blob size");
return ASN1_INVALID_LENGTH;
}
return len;
@@ -377,7 +376,7 @@ void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
oid = asn1_known_oid(object);
if (oid != OID_UNKNOWN)
{
- DBG2(" '%s'", oid_names[oid].name);
+ DBG2(DBG_LIB, " '%s'", oid_names[oid].name);
return;
}
break;
@@ -386,14 +385,14 @@ void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
case ASN1_PRINTABLESTRING:
case ASN1_T61STRING:
case ASN1_VISIBLESTRING:
- DBG2(" '%.*s'", (int)object.len, object.ptr);
+ DBG2(DBG_LIB, " '%.*s'", (int)object.len, object.ptr);
return;
case ASN1_UTCTIME:
case ASN1_GENERALIZEDTIME:
{
time_t time = asn1_to_time(&object, type);
- DBG2(" '%T'", &time, TRUE);
+ DBG2(DBG_LIB, " '%T'", &time, TRUE);
}
return;
default:
@@ -401,11 +400,11 @@ void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
}
if (private)
{
- DBG4("%B", &object);
+ DBG4(DBG_LIB, "%B", &object);
}
else
{
- DBG3("%B", &object);
+ DBG3(DBG_LIB, "%B", &object);
}
}
@@ -419,13 +418,14 @@ bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level, const c
/* an ASN.1 object must possess at least a tag and length field */
if (object->len < 2)
{
- DBG2("L%d - %s: ASN.1 object smaller than 2 octets", level, name);
+ DBG2(DBG_LIB, "L%d - %s: ASN.1 object smaller than 2 octets", level,
+ name);
return FALSE;
}
if (*object->ptr != type)
{
- DBG2("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
+ DBG2(DBG_LIB, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
level, name, type, *object->ptr);
return FALSE;
}
@@ -434,12 +434,12 @@ bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level, const c
if (len == ASN1_INVALID_LENGTH || object->len < len)
{
- DBG2("L%d - %s: length of ASN.1 object invalid or too large",
+ DBG2(DBG_LIB, "L%d - %s: length of ASN.1 object invalid or too large",
level, name);
return FALSE;
}
- DBG2("L%d - %s:", level, name);
+ DBG2(DBG_LIB, "L%d - %s:", level, name);
asn1_debug_simple_object(*object, type, FALSE);
return TRUE;
}
@@ -501,7 +501,7 @@ bool is_asn1(chunk_t blob)
if (tag != ASN1_SEQUENCE && tag != ASN1_SET && tag != ASN1_OCTET_STRING)
{
- DBG2(" file content is not binary ASN.1");
+ DBG2(DBG_LIB, " file content is not binary ASN.1");
return FALSE;
}
@@ -519,7 +519,7 @@ bool is_asn1(chunk_t blob)
return TRUE;
}
- DBG2(" file size does not match ASN.1 coded length");
+ DBG2(DBG_LIB, " file size does not match ASN.1 coded length");
return FALSE;
}
diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h
index d29190df7..866c28095 100644
--- a/src/libstrongswan/asn1/asn1.h
+++ b/src/libstrongswan/asn1/asn1.h
@@ -25,8 +25,7 @@
#include <stdarg.h>
-#include <utils.h>
-#include <chunk.h>
+#include <library.h>
/**
* Definition of some primitive ASN1 types
diff --git a/src/libstrongswan/asn1/asn1_parser.c b/src/libstrongswan/asn1/asn1_parser.c
index dc7726ad7..3e5bbbabd 100644
--- a/src/libstrongswan/asn1/asn1_parser.c
+++ b/src/libstrongswan/asn1/asn1_parser.c
@@ -19,7 +19,6 @@
#include <string.h>
#include <time.h>
-#include <utils.h>
#include <debug.h>
#include "asn1.h"
@@ -123,7 +122,7 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
{
/* field is missing */
- DBG2("L%d - %s:", level, obj.name);
+ DBG2(DBG_LIB, "L%d - %s:", level, obj.name);
if (obj.type & ASN1_CONSTRUCTED)
{
this->line++ ; /* skip context-specific tag */
@@ -150,7 +149,7 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
if (blob->len < 2)
{
- DBG1("L%d - %s: ASN.1 object smaller than 2 octets",
+ DBG1(DBG_LIB, "L%d - %s: ASN.1 object smaller than 2 octets",
level, obj.name);
this->success = FALSE;
goto end;
@@ -160,7 +159,7 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
if (blob1->len == ASN1_INVALID_LENGTH)
{
- DBG1("L%d - %s: length of ASN.1 object invalid or too large",
+ DBG1(DBG_LIB, "L%d - %s: length of ASN.1 object invalid or too large",
level, obj.name);
this->success = FALSE;
}
@@ -173,7 +172,7 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
if (obj.flags & ASN1_RAW)
{
- DBG2("L%d - %s:", level, obj.name);
+ DBG2(DBG_LIB, "L%d - %s:", level, obj.name);
object->ptr = start_ptr;
object->len = (size_t)(blob->ptr - start_ptr);
goto end;
@@ -181,14 +180,14 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
{
- DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
+ DBG1(DBG_LIB, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
level, obj.name, obj.type, *start_ptr);
- DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
+ DBG3(DBG_LIB, "%b", start_ptr, (u_int)(blob->ptr - start_ptr));
this->success = FALSE;
goto end;
}
- DBG2("L%d - %s:", level, obj.name);
+ DBG2(DBG_LIB, "L%d - %s:", level, obj.name);
/* In case of "SEQUENCE OF" or "SET OF" start a loop */
if (obj.flags & ASN1_LOOP)
@@ -217,11 +216,11 @@ static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
object->len = (size_t)(blob->ptr - start_ptr);
if (this->private)
{
- DBG4("%B", object);
+ DBG4(DBG_LIB, "%B", object);
}
else
{
- DBG3("%B", object);
+ DBG3(DBG_LIB, "%B", object);
}
}
else if (obj.flags & ASN1_BODY)
diff --git a/src/libstrongswan/asn1/asn1_parser.h b/src/libstrongswan/asn1/asn1_parser.h
index 49325232d..0edc22c23 100644
--- a/src/libstrongswan/asn1/asn1_parser.h
+++ b/src/libstrongswan/asn1/asn1_parser.h
@@ -25,9 +25,9 @@
#include <stdarg.h>
-#include <utils.h>
-#include <chunk.h>
-#include <asn1/asn1.h>
+#include <library.h>
+
+#include "asn1.h"
/**
* Definition of ASN.1 flags
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index 32e2eb033..aa1fd31b0 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -41,6 +41,7 @@ extern const oid_t oid_names[];
#define OID_UNIQUE_IDENTIFIER 34
#define OID_ROLE 35
#define OID_SUBJECT_KEY_ID 38
+#define OID_KEY_USAGE 39
#define OID_SUBJECT_ALT_NAME 41
#define OID_BASIC_CONSTRAINTS 43
#define OID_CRL_NUMBER 44
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index 203bc1f28..5d729c2eb 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -37,7 +37,7 @@
0x1D "id-ce"
0x09 "subjectDirectoryAttrs"
0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID
- 0x0F "keyUsage"
+ 0x0F "keyUsage" OID_KEY_USAGE
0x10 "privateKeyUsagePeriod"
0x11 "subjectAltName" OID_SUBJECT_ALT_NAME
0x12 "issuerAltName"
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index 86436e997..ef69eb4e7 100644
--- a/src/libstrongswan/chunk.c
+++ b/src/libstrongswan/chunk.c
@@ -22,8 +22,7 @@
#include <ctype.h>
#include "chunk.h"
-
-#include <debug.h>
+#include "debug.h"
/* required for chunk_hash */
#undef get16bits
@@ -222,7 +221,7 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force
if (!force && access(path, F_OK) == 0)
{
- DBG1(" %s file '%s' already exists", label, path);
+ DBG1(DBG_LIB, " %s file '%s' already exists", label, path);
return FALSE;
}
oldmask = umask(mask);
@@ -231,20 +230,21 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force
{
if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
{
- DBG1(" written %s file '%s' (%d bytes)",
+ DBG1(DBG_LIB, " written %s file '%s' (%d bytes)",
label, path, chunk.len);
good = TRUE;
}
else
{
- DBG1(" writing %s file '%s' failed: %s",
+ DBG1(DBG_LIB, " writing %s file '%s' failed: %s",
label, path, strerror(errno));
}
fclose(fd);
}
else
{
- DBG1(" could not open %s file '%s': %s", label, path, strerror(errno));
+ DBG1(DBG_LIB, " could not open %s file '%s': %s", label, path,
+ strerror(errno));
}
umask(oldmask);
return good;
@@ -497,7 +497,7 @@ bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace)
* Described in header.
*
* The implementation is based on Paul Hsieh's SuperFastHash:
- * http://www.azillionmonkeys.com/qed/hash.html
+ * http://www.azillionmonkeys.com/qed/hash.html
*/
u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
{
diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h
index a526f4a89..f0f9a7366 100644
--- a/src/libstrongswan/chunk.h
+++ b/src/libstrongswan/chunk.h
@@ -42,7 +42,7 @@ struct chunk_t {
size_t len;
};
-#include <utils.h>
+#include "utils.h"
/**
* A { NULL, 0 }-chunk handy for initialization.
diff --git a/src/libstrongswan/credentials/credential_factory.c b/src/libstrongswan/credentials/credential_factory.c
index 5139ad504..7cc7dbe0e 100644
--- a/src/libstrongswan/credentials/credential_factory.c
+++ b/src/libstrongswan/credentials/credential_factory.c
@@ -151,7 +151,7 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
{
names = certificate_type_names;
}
- DBG1("building %N - %N failed, tried %d builders",
+ DBG1(DBG_LIB, "building %N - %N failed, tried %d builders",
credential_type_names, type, names, subtype, failures);
}
this->recursive->set(this->recursive, (void*)level);
diff --git a/src/libstrongswan/credentials/keys/key_encoding.h b/src/libstrongswan/credentials/keys/key_encoding.h
index 384117166..d8435f4b4 100644
--- a/src/libstrongswan/credentials/keys/key_encoding.h
+++ b/src/libstrongswan/credentials/keys/key_encoding.h
@@ -79,7 +79,7 @@ enum key_encoding_type_t {
KEY_PRIV_ASN1_DER,
/** subjectPublicKeyInfo encoding */
KEY_PUB_SPKI_ASN1_DER,
- /** PEM oncoded PKCS#1 key */
+ /** PEM encoded PKCS#1 key */
KEY_PUB_PEM,
KEY_PRIV_PEM,
/** PGP key encoding */
diff --git a/src/libstrongswan/credentials/keys/shared_key.h b/src/libstrongswan/credentials/keys/shared_key.h
index fe7bc86be..d00b8d12e 100644
--- a/src/libstrongswan/credentials/keys/shared_key.h
+++ b/src/libstrongswan/credentials/keys/shared_key.h
@@ -41,6 +41,8 @@ enum shared_key_type_t {
SHARED_PRIVATE_KEY_PASS,
/** PIN to unlock a smartcard */
SHARED_PIN,
+ /** Calculated NT Hash = MD4(UTF-16LE(password)) */
+ SHARED_NT_HASH,
};
/**
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 46b50329d..fee71953d 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -686,7 +686,7 @@ static void add_test_vector(private_crypto_factory_t *this,
case RANDOM_NUMBER_GENERATOR:
return this->tester->add_rng_vector(this->tester, vector);
default:
- DBG1("%N test vectors not supported, ignored",
+ DBG1(DBG_LIB, "%N test vectors not supported, ignored",
transform_type_names, type);
}
}
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index 86daf65f9..76cc1cf2c 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -136,7 +136,7 @@ static bool test_crypter(private_crypto_tester_t *this,
crypter->destroy(crypter);
if (failed)
{
- DBG1("disabled %N: test vector %u failed",
+ DBG1(DBG_LIB, "disabled %N: test vector %u failed",
encryption_algorithm_names, alg, tested);
break;
}
@@ -144,14 +144,14 @@ static bool test_crypter(private_crypto_tester_t *this,
enumerator->destroy(enumerator);
if (!tested)
{
- DBG1("%s %N: no test vectors found",
+ DBG1(DBG_LIB, "%s %N: no test vectors found",
this->required ? "disabled" : "enabled ",
encryption_algorithm_names, alg);
return !this->required;
}
if (!failed)
{
- DBG1("enabled %N: passed %u test vectors",
+ DBG1(DBG_LIB, "enabled %N: passed %u test vectors",
encryption_algorithm_names, alg, tested);
}
return !failed;
@@ -183,7 +183,7 @@ static bool test_signer(private_crypto_tester_t *this,
signer = create(alg);
if (!signer)
{
- DBG1("disabled %N: creating instance failed",
+ DBG1(DBG_LIB, "disabled %N: creating instance failed",
integrity_algorithm_names, alg);
failed = TRUE;
break;
@@ -240,7 +240,7 @@ static bool test_signer(private_crypto_tester_t *this,
signer->destroy(signer);
if (failed)
{
- DBG1("disabled %N: test vector %u failed",
+ DBG1(DBG_LIB, "disabled %N: test vector %u failed",
integrity_algorithm_names, alg, tested);
break;
}
@@ -248,14 +248,14 @@ static bool test_signer(private_crypto_tester_t *this,
enumerator->destroy(enumerator);
if (!tested)
{
- DBG1("%s %N: no test vectors found",
+ DBG1(DBG_LIB, "%s %N: no test vectors found",
this->required ? "disabled" : "enabled ",
integrity_algorithm_names, alg);
return !this->required;
}
if (!failed)
{
- DBG1("enabled %N: passed %u test vectors",
+ DBG1(DBG_LIB, "enabled %N: passed %u test vectors",
integrity_algorithm_names, alg, tested);
}
return !failed;
@@ -287,7 +287,7 @@ static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
hasher = create(alg);
if (!hasher)
{
- DBG1("disabled %N: creating instance failed",
+ DBG1(DBG_LIB, "disabled %N: creating instance failed",
hash_algorithm_names, alg);
failed = TRUE;
break;
@@ -330,7 +330,7 @@ static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
hasher->destroy(hasher);
if (failed)
{
- DBG1("disabled %N: test vector %u failed",
+ DBG1(DBG_LIB, "disabled %N: test vector %u failed",
hash_algorithm_names, alg, tested);
break;
}
@@ -338,14 +338,14 @@ static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
enumerator->destroy(enumerator);
if (!tested)
{
- DBG1("%s %N: no test vectors found",
+ DBG1(DBG_LIB, "%s %N: no test vectors found",
this->required ? "disabled" : "enabled ",
hash_algorithm_names, alg);
return !this->required;
}
if (!failed)
{
- DBG1("enabled %N: passed %u test vectors",
+ DBG1(DBG_LIB, "enabled %N: passed %u test vectors",
hash_algorithm_names, alg, tested);
}
return !failed;
@@ -377,7 +377,7 @@ static bool test_prf(private_crypto_tester_t *this,
prf = create(alg);
if (!prf)
{
- DBG1("disabled %N: creating instance failed",
+ DBG1(DBG_LIB, "disabled %N: creating instance failed",
pseudo_random_function_names, alg);
failed = TRUE;
break;
@@ -431,7 +431,7 @@ static bool test_prf(private_crypto_tester_t *this,
prf->destroy(prf);
if (failed)
{
- DBG1("disabled %N: test vector %u failed",
+ DBG1(DBG_LIB, "disabled %N: test vector %u failed",
pseudo_random_function_names, alg, tested);
break;
}
@@ -439,14 +439,14 @@ static bool test_prf(private_crypto_tester_t *this,
enumerator->destroy(enumerator);
if (!tested)
{
- DBG1("%s %N: no test vectors found",
+ DBG1(DBG_LIB, "%s %N: no test vectors found",
this->required ? "disabled" : "enabled ",
pseudo_random_function_names, alg);
return !this->required;
}
if (!failed)
{
- DBG1("enabled %N: passed %u test vectors",
+ DBG1(DBG_LIB, "enabled %N: passed %u test vectors",
pseudo_random_function_names, alg, tested);
}
return !failed;
@@ -465,7 +465,7 @@ static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
if (!this->rng_true && quality == RNG_TRUE)
{
- DBG1("enabled %N: skipping test (disabled by config)",
+ DBG1(DBG_LIB, "enabled %N: skipping test (disabled by config)",
rng_quality_names, quality);
return TRUE;
}
@@ -485,7 +485,7 @@ static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
rng = create(quality);
if (!rng)
{
- DBG1("disabled %N: creating instance failed",
+ DBG1(DBG_LIB, "disabled %N: creating instance failed",
rng_quality_names, quality);
failed = TRUE;
break;
@@ -515,7 +515,7 @@ static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
rng->destroy(rng);
if (failed)
{
- DBG1("disabled %N: test vector %u failed",
+ DBG1(DBG_LIB, "disabled %N: test vector %u failed",
rng_quality_names, quality, tested);
break;
}
@@ -523,14 +523,14 @@ static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
enumerator->destroy(enumerator);
if (!tested)
{
- DBG1("%s %N: no test vectors found",
+ DBG1(DBG_LIB, "%s %N: no test vectors found",
this->required ? ", disabled" : "enabled ",
rng_quality_names, quality);
return !this->required;
}
if (!failed)
{
- DBG1("enabled %N: passed %u test vectors",
+ DBG1(DBG_LIB, "enabled %N: passed %u test vectors",
rng_quality_names, quality, tested);
}
return !failed;
diff --git a/src/libstrongswan/crypto/diffie_hellman.c b/src/libstrongswan/crypto/diffie_hellman.c
index 18d532697..9bd8991fc 100644
--- a/src/libstrongswan/crypto/diffie_hellman.c
+++ b/src/libstrongswan/crypto/diffie_hellman.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -31,10 +32,412 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
"ECP_256",
"ECP_384",
"ECP_521");
-ENUM_NEXT(diffie_hellman_group_names, ECP_192_BIT, ECP_224_BIT, ECP_521_BIT,
+ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, ECP_224_BIT, ECP_521_BIT,
+ "MODP_1024_160",
+ "MODP_2048_224",
+ "MODP_2048_256",
"ECP_192",
"ECP_224");
ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_NULL, ECP_224_BIT,
"MODP_NULL");
ENUM_END(diffie_hellman_group_names, MODP_NULL);
+
+/**
+ * List of known diffie hellman group parameters.
+ */
+static struct {
+ /* Public part of the struct */
+ diffie_hellman_params_t public;
+ /* The group identifier as specified in IKEv2 */
+ diffie_hellman_group_t group;
+ /* Optimal length of the exponent (in bytes), as specified in RFC 3526. */
+ size_t opt_exp;
+} dh_params[] = {
+ {
+ .group = MODP_768_BIT, .opt_exp = 32, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_1024_BIT, .opt_exp = 32, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_1536_BIT, .opt_exp = 32, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_2048_BIT, .opt_exp = 48, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
+ 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
+ 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
+ 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
+ 0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_3072_BIT, .opt_exp = 48, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
+ 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
+ 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
+ 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
+ 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
+ 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
+ 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
+ 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
+ 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
+ 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
+ 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
+ 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
+ 0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_4096_BIT, .opt_exp = 64, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
+ 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
+ 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
+ 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
+ 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
+ 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
+ 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
+ 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
+ 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
+ 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
+ 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
+ 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
+ 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
+ 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
+ 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
+ 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
+ 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
+ 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
+ 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
+ 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
+ 0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_6144_BIT, .opt_exp = 64, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
+ 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
+ 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
+ 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
+ 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
+ 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
+ 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
+ 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
+ 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
+ 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
+ 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
+ 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
+ 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
+ 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
+ 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
+ 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
+ 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
+ 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
+ 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
+ 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
+ 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
+ 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
+ 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
+ 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
+ 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
+ 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
+ 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
+ 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
+ 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
+ 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
+ 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
+ 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
+ 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
+ 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
+ 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
+ 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
+ 0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_8192_BIT, .opt_exp = 64, .public = {
+ .generator = chunk_from_chars(0x02),
+ .prime = chunk_from_chars(
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
+ 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
+ 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+ 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
+ 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
+ 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+ 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
+ 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
+ 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+ 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
+ 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
+ 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
+ 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
+ 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
+ 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
+ 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
+ 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
+ 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
+ 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
+ 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
+ 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
+ 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
+ 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
+ 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
+ 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
+ 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
+ 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
+ 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
+ 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
+ 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
+ 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
+ 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
+ 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
+ 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
+ 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
+ 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
+ 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
+ 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
+ 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
+ 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
+ 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
+ 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
+ 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
+ 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
+ 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
+ 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
+ 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
+ 0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
+ 0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA,
+ 0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,
+ 0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
+ 0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D,
+ 0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,
+ 0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
+ 0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8,
+ 0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,
+ 0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
+ 0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D,
+ 0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,
+ 0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
+ 0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B,
+ 0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,
+ 0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
+ 0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ },
+ },{
+ .group = MODP_1024_160, .opt_exp = 20, .public = {
+ .subgroup = chunk_from_chars(
+ 0xF5,0x18,0xAA,0x87,0x81,0xA8,0xDF,0x27,0x8A,0xBA,0x4E,0x7D,0x64,0xB7,0xCB,0x9D,
+ 0x49,0x46,0x23,0x53),
+ .generator = chunk_from_chars(
+ 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,0xEF,0xB9,0x99,0x05,
+ 0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,
+ 0x26,0x6F,0xEA,0x1E,0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
+ 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,0x9E,0x27,0x49,0xF4,
+ 0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,
+ 0xA6,0xA2,0x4C,0x08,0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
+ 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,0x18,0xD0,0x8B,0xC8,
+ 0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5),
+ .prime = chunk_from_chars(
+ 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,0xAE,0x5D,0x54,0xEC,
+ 0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,
+ 0x60,0x73,0xE2,0x86,0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
+ 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,0xD4,0x9B,0x83,0xBF,
+ 0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,
+ 0x4E,0xFF,0xD6,0xFA,0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
+ 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,0x36,0x5C,0x1A,0x65,
+ 0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71),
+ },
+ }, {
+ .group = MODP_2048_224, .opt_exp = 28, .public = {
+ .subgroup = chunk_from_chars(
+ 0x80,0x1C,0x0D,0x34,0xC5,0x8D,0x93,0xFE,0x99,0x71,0x77,0x10,0x1F,0x80,0x53,0x5A,
+ 0x47,0x38,0xCE,0xBC,0xBF,0x38,0x9A,0x99,0xB3,0x63,0x71,0xEB),
+ .generator = chunk_from_chars(
+ 0xAC,0x40,0x32,0xEF,0x4F,0x2D,0x9A,0xE3,0x9D,0xF3,0x0B,0x5C,0x8F,0xFD,0xAC,0x50,
+ 0x6C,0xDE,0xBE,0x7B,0x89,0x99,0x8C,0xAF,0x74,0x86,0x6A,0x08,0xCF,0xE4,0xFF,0xE3,
+ 0xA6,0x82,0x4A,0x4E,0x10,0xB9,0xA6,0xF0,0xDD,0x92,0x1F,0x01,0xA7,0x0C,0x4A,0xFA,
+ 0xAB,0x73,0x9D,0x77,0x00,0xC2,0x9F,0x52,0xC5,0x7D,0xB1,0x7C,0x62,0x0A,0x86,0x52,
+ 0xBE,0x5E,0x90,0x01,0xA8,0xD6,0x6A,0xD7,0xC1,0x76,0x69,0x10,0x19,0x99,0x02,0x4A,
+ 0xF4,0xD0,0x27,0x27,0x5A,0xC1,0x34,0x8B,0xB8,0xA7,0x62,0xD0,0x52,0x1B,0xC9,0x8A,
+ 0xE2,0x47,0x15,0x04,0x22,0xEA,0x1E,0xD4,0x09,0x93,0x9D,0x54,0xDA,0x74,0x60,0xCD,
+ 0xB5,0xF6,0xC6,0xB2,0x50,0x71,0x7C,0xBE,0xF1,0x80,0xEB,0x34,0x11,0x8E,0x98,0xD1,
+ 0x19,0x52,0x9A,0x45,0xD6,0xF8,0x34,0x56,0x6E,0x30,0x25,0xE3,0x16,0xA3,0x30,0xEF,
+ 0xBB,0x77,0xA8,0x6F,0x0C,0x1A,0xB1,0x5B,0x05,0x1A,0xE3,0xD4,0x28,0xC8,0xF8,0xAC,
+ 0xB7,0x0A,0x81,0x37,0x15,0x0B,0x8E,0xEB,0x10,0xE1,0x83,0xED,0xD1,0x99,0x63,0xDD,
+ 0xD9,0xE2,0x63,0xE4,0x77,0x05,0x89,0xEF,0x6A,0xA2,0x1E,0x7F,0x5F,0x2F,0xF3,0x81,
+ 0xB5,0x39,0xCC,0xE3,0x40,0x9D,0x13,0xCD,0x56,0x6A,0xFB,0xB4,0x8D,0x6C,0x01,0x91,
+ 0x81,0xE1,0xBC,0xFE,0x94,0xB3,0x02,0x69,0xED,0xFE,0x72,0xFE,0x9B,0x6A,0xA4,0xBD,
+ 0x7B,0x5A,0x0F,0x1C,0x71,0xCF,0xFF,0x4C,0x19,0xC4,0x18,0xE1,0xF6,0xEC,0x01,0x79,
+ 0x81,0xBC,0x08,0x7F,0x2A,0x70,0x65,0xB3,0x84,0xB8,0x90,0xD3,0x19,0x1F,0x2B,0xFA),
+ .prime = chunk_from_chars(
+ 0xAD,0x10,0x7E,0x1E,0x91,0x23,0xA9,0xD0,0xD6,0x60,0xFA,0xA7,0x95,0x59,0xC5,0x1F,
+ 0xA2,0x0D,0x64,0xE5,0x68,0x3B,0x9F,0xD1,0xB5,0x4B,0x15,0x97,0xB6,0x1D,0x0A,0x75,
+ 0xE6,0xFA,0x14,0x1D,0xF9,0x5A,0x56,0xDB,0xAF,0x9A,0x3C,0x40,0x7B,0xA1,0xDF,0x15,
+ 0xEB,0x3D,0x68,0x8A,0x30,0x9C,0x18,0x0E,0x1D,0xE6,0xB8,0x5A,0x12,0x74,0xA0,0xA6,
+ 0x6D,0x3F,0x81,0x52,0xAD,0x6A,0xC2,0x12,0x90,0x37,0xC9,0xED,0xEF,0xDA,0x4D,0xF8,
+ 0xD9,0x1E,0x8F,0xEF,0x55,0xB7,0x39,0x4B,0x7A,0xD5,0xB7,0xD0,0xB6,0xC1,0x22,0x07,
+ 0xC9,0xF9,0x8D,0x11,0xED,0x34,0xDB,0xF6,0xC6,0xBA,0x0B,0x2C,0x8B,0xBC,0x27,0xBE,
+ 0x6A,0x00,0xE0,0xA0,0xB9,0xC4,0x97,0x08,0xB3,0xBF,0x8A,0x31,0x70,0x91,0x88,0x36,
+ 0x81,0x28,0x61,0x30,0xBC,0x89,0x85,0xDB,0x16,0x02,0xE7,0x14,0x41,0x5D,0x93,0x30,
+ 0x27,0x82,0x73,0xC7,0xDE,0x31,0xEF,0xDC,0x73,0x10,0xF7,0x12,0x1F,0xD5,0xA0,0x74,
+ 0x15,0x98,0x7D,0x9A,0xDC,0x0A,0x48,0x6D,0xCD,0xF9,0x3A,0xCC,0x44,0x32,0x83,0x87,
+ 0x31,0x5D,0x75,0xE1,0x98,0xC6,0x41,0xA4,0x80,0xCD,0x86,0xA1,0xB9,0xE5,0x87,0xE8,
+ 0xBE,0x60,0xE6,0x9C,0xC9,0x28,0xB2,0xB9,0xC5,0x21,0x72,0xE4,0x13,0x04,0x2E,0x9B,
+ 0x23,0xF1,0x0B,0x0E,0x16,0xE7,0x97,0x63,0xC9,0xB5,0x3D,0xCF,0x4B,0xA8,0x0A,0x29,
+ 0xE3,0xFB,0x73,0xC1,0x6B,0x8E,0x75,0xB9,0x7E,0xF3,0x63,0xE2,0xFF,0xA3,0x1F,0x71,
+ 0xCF,0x9D,0xE5,0x38,0x4E,0x71,0xB8,0x1C,0x0A,0xC4,0xDF,0xFE,0x0C,0x10,0xE6,0x4F)
+ },
+ },{
+ .group = MODP_2048_256, .opt_exp = 32, .public = {
+ .subgroup = chunk_from_chars(
+ 0x8C,0xF8,0x36,0x42,0xA7,0x09,0xA0,0x97,0xB4,0x47,0x99,0x76,0x40,0x12,0x9D,0xA2,
+ 0x99,0xB1,0xA4,0x7D,0x1E,0xB3,0x75,0x0B,0xA3,0x08,0xB0,0xFE,0x64,0xF5,0xFB,0xD3),
+ .generator = chunk_from_chars(
+ 0x3F,0xB3,0x2C,0x9B,0x73,0x13,0x4D,0x0B,0x2E,0x77,0x50,0x66,0x60,0xED,0xBD,0x48,
+ 0x4C,0xA7,0xB1,0x8F,0x21,0xEF,0x20,0x54,0x07,0xF4,0x79,0x3A,0x1A,0x0B,0xA1,0x25,
+ 0x10,0xDB,0xC1,0x50,0x77,0xBE,0x46,0x3F,0xFF,0x4F,0xED,0x4A,0xAC,0x0B,0xB5,0x55,
+ 0xBE,0x3A,0x6C,0x1B,0x0C,0x6B,0x47,0xB1,0xBC,0x37,0x73,0xBF,0x7E,0x8C,0x6F,0x62,
+ 0x90,0x12,0x28,0xF8,0xC2,0x8C,0xBB,0x18,0xA5,0x5A,0xE3,0x13,0x41,0x00,0x0A,0x65,
+ 0x01,0x96,0xF9,0x31,0xC7,0x7A,0x57,0xF2,0xDD,0xF4,0x63,0xE5,0xE9,0xEC,0x14,0x4B,
+ 0x77,0x7D,0xE6,0x2A,0xAA,0xB8,0xA8,0x62,0x8A,0xC3,0x76,0xD2,0x82,0xD6,0xED,0x38,
+ 0x64,0xE6,0x79,0x82,0x42,0x8E,0xBC,0x83,0x1D,0x14,0x34,0x8F,0x6F,0x2F,0x91,0x93,
+ 0xB5,0x04,0x5A,0xF2,0x76,0x71,0x64,0xE1,0xDF,0xC9,0x67,0xC1,0xFB,0x3F,0x2E,0x55,
+ 0xA4,0xBD,0x1B,0xFF,0xE8,0x3B,0x9C,0x80,0xD0,0x52,0xB9,0x85,0xD1,0x82,0xEA,0x0A,
+ 0xDB,0x2A,0x3B,0x73,0x13,0xD3,0xFE,0x14,0xC8,0x48,0x4B,0x1E,0x05,0x25,0x88,0xB9,
+ 0xB7,0xD2,0xBB,0xD2,0xDF,0x01,0x61,0x99,0xEC,0xD0,0x6E,0x15,0x57,0xCD,0x09,0x15,
+ 0xB3,0x35,0x3B,0xBB,0x64,0xE0,0xEC,0x37,0x7F,0xD0,0x28,0x37,0x0D,0xF9,0x2B,0x52,
+ 0xC7,0x89,0x14,0x28,0xCD,0xC6,0x7E,0xB6,0x18,0x4B,0x52,0x3D,0x1D,0xB2,0x46,0xC3,
+ 0x2F,0x63,0x07,0x84,0x90,0xF0,0x0E,0xF8,0xD6,0x47,0xD1,0x48,0xD4,0x79,0x54,0x51,
+ 0x5E,0x23,0x27,0xCF,0xEF,0x98,0xC5,0x82,0x66,0x4B,0x4C,0x0F,0x6C,0xC4,0x16,0x59),
+ .prime = chunk_from_chars(
+ 0x87,0xA8,0xE6,0x1D,0xB4,0xB6,0x66,0x3C,0xFF,0xBB,0xD1,0x9C,0x65,0x19,0x59,0x99,
+ 0x8C,0xEE,0xF6,0x08,0x66,0x0D,0xD0,0xF2,0x5D,0x2C,0xEE,0xD4,0x43,0x5E,0x3B,0x00,
+ 0xE0,0x0D,0xF8,0xF1,0xD6,0x19,0x57,0xD4,0xFA,0xF7,0xDF,0x45,0x61,0xB2,0xAA,0x30,
+ 0x16,0xC3,0xD9,0x11,0x34,0x09,0x6F,0xAA,0x3B,0xF4,0x29,0x6D,0x83,0x0E,0x9A,0x7C,
+ 0x20,0x9E,0x0C,0x64,0x97,0x51,0x7A,0xBD,0x5A,0x8A,0x9D,0x30,0x6B,0xCF,0x67,0xED,
+ 0x91,0xF9,0xE6,0x72,0x5B,0x47,0x58,0xC0,0x22,0xE0,0xB1,0xEF,0x42,0x75,0xBF,0x7B,
+ 0x6C,0x5B,0xFC,0x11,0xD4,0x5F,0x90,0x88,0xB9,0x41,0xF5,0x4E,0xB1,0xE5,0x9B,0xB8,
+ 0xBC,0x39,0xA0,0xBF,0x12,0x30,0x7F,0x5C,0x4F,0xDB,0x70,0xC5,0x81,0xB2,0x3F,0x76,
+ 0xB6,0x3A,0xCA,0xE1,0xCA,0xA6,0xB7,0x90,0x2D,0x52,0x52,0x67,0x35,0x48,0x8A,0x0E,
+ 0xF1,0x3C,0x6D,0x9A,0x51,0xBF,0xA4,0xAB,0x3A,0xD8,0x34,0x77,0x96,0x52,0x4D,0x8E,
+ 0xF6,0xA1,0x67,0xB5,0xA4,0x18,0x25,0xD9,0x67,0xE1,0x44,0xE5,0x14,0x05,0x64,0x25,
+ 0x1C,0xCA,0xCB,0x83,0xE6,0xB4,0x86,0xF6,0xB3,0xCA,0x3F,0x79,0x71,0x50,0x60,0x26,
+ 0xC0,0xB8,0x57,0xF6,0x89,0x96,0x28,0x56,0xDE,0xD4,0x01,0x0A,0xBD,0x0B,0xE6,0x21,
+ 0xC3,0xA3,0x96,0x0A,0x54,0xE7,0x10,0xC3,0x75,0xF2,0x63,0x75,0xD7,0x01,0x41,0x03,
+ 0xA4,0xB5,0x43,0x30,0xC1,0x98,0xAF,0x12,0x61,0x16,0xD2,0x27,0x6E,0x11,0x71,0x5F,
+ 0x69,0x38,0x77,0xFA,0xD7,0xEF,0x09,0xCA,0xDB,0x09,0x4A,0xE9,0x1E,0x1A,0x15,0x97)
+ },
+ },
+};
+
+/**
+ * Described in header.
+ */
+diffie_hellman_params_t *diffie_hellman_get_params(diffie_hellman_group_t group)
+{
+ int i;
+
+ for (i = 0; i < countof(dh_params); i++)
+ {
+ if (dh_params[i].group == group)
+ {
+ if (!dh_params[i].public.exp_len)
+ {
+ if (!dh_params[i].public.subgroup.len &&
+ lib->settings->get_int(lib->settings,
+ "libstrongswan.dh_exponent_ansi_x9_42", TRUE))
+ {
+ dh_params[i].public.exp_len = dh_params[i].public.prime.len;
+ }
+ else
+ {
+ dh_params[i].public.exp_len = dh_params[i].opt_exp;
+ }
+ }
+ return &dh_params[i].public;
+ }
+ }
+ return NULL;
+}
+
diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h
index 842938c3b..cdc9c785e 100644
--- a/src/libstrongswan/crypto/diffie_hellman.h
+++ b/src/libstrongswan/crypto/diffie_hellman.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -24,6 +25,7 @@
typedef enum diffie_hellman_group_t diffie_hellman_group_t;
typedef struct diffie_hellman_t diffie_hellman_t;
+typedef struct diffie_hellman_params_t diffie_hellman_params_t;
#include <library.h>
@@ -48,6 +50,9 @@ enum diffie_hellman_group_t {
ECP_256_BIT = 19,
ECP_384_BIT = 20,
ECP_521_BIT = 21,
+ MODP_1024_160 = 22,
+ MODP_2048_224 = 23,
+ MODP_2048_256 = 24,
ECP_192_BIT = 25,
ECP_224_BIT = 26,
/** insecure NULL diffie hellman group for testing, in PRIVATE USE */
@@ -70,8 +75,8 @@ struct diffie_hellman_t {
* Space for returned secret is allocated and must be
* freed by the caller.
*
- * @param secret shared secret will be written into this chunk
- * @return SUCCESS, FAILED if not both DH values are set
+ * @param secret shared secret will be written into this chunk
+ * @return SUCCESS, FAILED if not both DH values are set
*/
status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret);
@@ -80,7 +85,7 @@ struct diffie_hellman_t {
*
* Chunk gets cloned and can be destroyed afterwards.
*
- * @param value public value of partner
+ * @param value public value of partner
*/
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value);
@@ -106,4 +111,38 @@ struct diffie_hellman_t {
void (*destroy) (diffie_hellman_t *this);
};
+/**
+ * Parameters for a specific diffie hellman group.
+ */
+struct diffie_hellman_params_t {
+
+ /**
+ * The prime of the group
+ */
+ const chunk_t prime;
+
+ /**
+ * Generator of the group
+ */
+ const chunk_t generator;
+
+ /**
+ * Exponent length to use
+ */
+ size_t exp_len;
+
+ /**
+ * Prime order subgroup; for MODP Groups 22-24
+ */
+ const chunk_t subgroup;
+};
+
+/**
+ * Get the parameters associated with the specified diffie hellman group.
+ *
+ * @param group DH group
+ * @return The parameters or NULL, if the group is not supported
+ */
+diffie_hellman_params_t *diffie_hellman_get_params(diffie_hellman_group_t group);
+
#endif /** DIFFIE_HELLMAN_H_ @}*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.c b/src/libstrongswan/crypto/proposal/proposal_keywords.c
index 75816e8b3..a43dde7ea 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.c
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.c
@@ -59,12 +59,12 @@ struct proposal_token {
u_int16_t keysize;
};
-#define TOTAL_KEYWORDS 89
+#define TOTAL_KEYWORDS 95
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 12
-#define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 123
-/* maximum key range = 120, duplicates = 0 */
+#define MIN_HASH_VALUE 5
+#define MAX_HASH_VALUE 137
+/* maximum key range = 133, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -80,32 +80,32 @@ hash (str, len)
{
static const unsigned char asso_values[] =
{
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 11,
- 2, 23, 5, 27, 21, 8, 5, 0, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 22, 124, 24, 0, 1,
- 8, 2, 50, 0, 11, 54, 124, 124, 0, 124,
- 42, 0, 124, 124, 5, 9, 34, 6, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 3, 11,
+ 2, 23, 29, 27, 21, 16, 5, 0, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 17, 138, 1, 0, 1,
+ 9, 9, 50, 0, 4, 54, 138, 138, 1, 138,
+ 35, 0, 138, 138, 71, 3, 38, 22, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138
};
register int hval = len;
@@ -135,108 +135,115 @@ hash (str, len)
static const struct proposal_token wordlist[] =
{
- {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
- {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
- {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
- {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
- {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
- {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
- {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
- {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
- {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
- {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
- {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
- {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
- {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
- {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
- {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
- {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
- {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
- {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
- {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
- {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
- {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
- {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
- {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
- {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
- {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
- {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
- {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
- {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
- {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
- {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
- {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
- {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
- {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
- {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
- {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256}
+ {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
+ {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
+ {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
+ {"aes192gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192},
+ {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"aes128gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128},
+ {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
+ {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
+ {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
+ {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
+ {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
+ {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
+ {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
+ {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
+ {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
+ {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
+ {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
+ {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
+ {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
+ {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
+ {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
+ {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
+ {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
+ {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
+ {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
+ {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
+ {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
+ {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
+ {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
+ {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
+ {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
+ {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
+ {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
+ {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
+ {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
+ {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
+ {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
+ {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
+ {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
+ {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
+ {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
+ {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256}
};
static const short lookup[] =
{
- -1, -1, -1, -1, 0, -1, -1, -1, 1, -1, 2, -1, 3, 4,
- 5, 6, -1, 7, 8, -1, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -1, 70,
- 71, 72, -1, -1, 73, 74, 75, 76, 77, -1, 78, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 79, 80, -1, -1, -1, -1, -1, 81,
- 82, 83, -1, 84, -1, -1, -1, 85, -1, 86, 87, 88
+ -1, -1, -1, -1, -1, 0, 1, -1, 2, -1, 3, -1, 4, 5,
+ 6, 7, -1, -1, -1, -1, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, 26, -1, -1,
+ 27, 28, 29, 30, 31, 32, 33, -1, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, -1, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, -1, 69, 70, 71, 72, 73, 74, 75, 76, -1, -1, 77,
+ 78, 79, 80, 81, -1, -1, 82, 83, -1, -1, 84, 85, -1, 86,
+ 87, 88, 89, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1,
+ -1, -1, -1, -1, 92, -1, 93, -1, -1, -1, -1, 94
};
#ifdef __GNUC__
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.txt b/src/libstrongswan/crypto/proposal/proposal_keywords.txt
index 139d689ca..338993821 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.txt
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.txt
@@ -29,92 +29,98 @@ struct proposal_token {
u_int16_t keysize;
};
%%
-null, ENCRYPTION_ALGORITHM, ENCR_NULL, 0
-des, ENCRYPTION_ALGORITHM, ENCR_DES, 0
-3des, ENCRYPTION_ALGORITHM, ENCR_3DES, 0
-aes, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128
-aes128, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128
-aes192, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192
-aes256, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256
-aes128ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128
-aes192ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192
-aes256ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256
-aes128ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
-aes128ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
-aes128ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
-aes128ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
-aes128ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
-aes128ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
-aes192ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
-aes192ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
-aes192ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
-aes192ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
-aes192ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
-aes192ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
-aes256ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
-aes256ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
-aes256ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
-aes256ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
-aes256ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
-aes256ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
-aes128gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
-aes128gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
-aes128gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
-aes128gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
-aes128gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
-aes128gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
-aes192gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
-aes192gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
-aes192gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
-aes192gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
-aes192gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
-aes192gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
-aes256gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
-aes256gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
-aes256gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
-aes256gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
-aes256gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
-aes256gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
-blowfish, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
-blowfish128, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
-blowfish192, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192
-blowfish256, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256
-camellia, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128
-camellia128, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128
-camellia192, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192
-camellia256, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256
-cast128, ENCRYPTION_ALGORITHM, ENCR_CAST, 128
-serpent, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128
-serpent128, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128
-serpent192, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192
-serpent256, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256
-twofish, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128
-twofish128, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128
-twofish192, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192
-twofish256, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256
-sha, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
-sha1, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
-sha256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
-sha2_256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
-sha256_96, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0
-sha2_256_96, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0
-sha384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
-sha2_384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
-sha512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
-sha2_512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
-md5, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0
-aesxcbc, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0
-modpnull, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0
-modp768, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0
-modp1024, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0
-modp1536, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0
-modp2048, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0
-modp3072, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0
-modp4096, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0
-modp6144, DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0
-modp8192, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0
-ecp192, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0
-ecp224, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0
-ecp256, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0
-ecp384, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0
-ecp521, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0
+null, ENCRYPTION_ALGORITHM, ENCR_NULL, 0
+des, ENCRYPTION_ALGORITHM, ENCR_DES, 0
+3des, ENCRYPTION_ALGORITHM, ENCR_3DES, 0
+aes, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128
+aes128, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128
+aes192, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192
+aes256, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256
+aes128ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128
+aes192ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192
+aes256ctr, ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256
+aes128ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
+aes128ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
+aes128ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
+aes128ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
+aes128ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
+aes128ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
+aes192ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
+aes192ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
+aes192ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
+aes192ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
+aes192ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
+aes192ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
+aes256ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
+aes256ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
+aes256ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
+aes256ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
+aes256ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
+aes256ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
+aes128gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
+aes128gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
+aes128gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
+aes128gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
+aes128gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
+aes128gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
+aes192gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
+aes192gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
+aes192gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
+aes192gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
+aes192gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
+aes192gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
+aes256gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
+aes256gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
+aes256gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
+aes256gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
+aes256gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
+aes256gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
+aes128gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128
+aes192gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192
+aes256gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256
+blowfish, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
+blowfish128, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
+blowfish192, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192
+blowfish256, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256
+camellia, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128
+camellia128, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128
+camellia192, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192
+camellia256, ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256
+cast128, ENCRYPTION_ALGORITHM, ENCR_CAST, 128
+serpent, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128
+serpent128, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128
+serpent192, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192
+serpent256, ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256
+twofish, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128
+twofish128, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128
+twofish192, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192
+twofish256, ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256
+sha, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
+sha1, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
+sha256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
+sha2_256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
+sha256_96, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0
+sha2_256_96, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0
+sha384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
+sha2_384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
+sha512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
+sha2_512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
+md5, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0
+aesxcbc, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0
+modpnull, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0
+modp768, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0
+modp1024, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0
+modp1536, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0
+modp2048, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0
+modp3072, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0
+modp4096, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0
+modp6144, DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0
+modp8192, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0
+ecp192, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0
+ecp224, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0
+ecp256, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0
+ecp384, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0
+ecp521, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0
+modp1024s160, DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0
+modp2048s224, DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0
+modp2048s256, DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0
diff --git a/src/libstrongswan/debug.c b/src/libstrongswan/debug.c
index 51b7875d8..21a7e63dd 100644
--- a/src/libstrongswan/debug.c
+++ b/src/libstrongswan/debug.c
@@ -17,10 +17,36 @@
#include "debug.h"
+ENUM(debug_names, DBG_DMN, DBG_LIB,
+ "DMN",
+ "MGR",
+ "IKE",
+ "CHD",
+ "JOB",
+ "CFG",
+ "KNL",
+ "NET",
+ "ENC",
+ "LIB",
+);
+
+ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
+ "dmn",
+ "mgr",
+ "ike",
+ "chd",
+ "job",
+ "cfg",
+ "knl",
+ "net",
+ "enc",
+ "lib",
+);
+
/**
* level logged by the default logger
*/
-static int default_level = 1;
+static level_t default_level = 1;
/**
* stream logged to by the default logger
@@ -30,7 +56,7 @@ static FILE *default_stream = NULL;
/**
* default dbg function which printf all to stderr
*/
-void dbg_default(int level, char *fmt, ...)
+void dbg_default(debug_t group, level_t level, char *fmt, ...)
{
if (!default_stream)
{
@@ -50,7 +76,7 @@ void dbg_default(int level, char *fmt, ...)
/**
* set the level logged by the default stderr logger
*/
-void dbg_default_set_level(int level)
+void dbg_default_set_level(level_t level)
{
default_level = level;
}
@@ -66,5 +92,5 @@ void dbg_default_set_stream(FILE *stream)
/**
* The registered debug hook.
*/
-void (*dbg) (int level, char *fmt, ...) = dbg_default;
+void (*dbg) (debug_t group, level_t level, char *fmt, ...) = dbg_default;
diff --git a/src/libstrongswan/debug.h b/src/libstrongswan/debug.h
index 085795acb..a21111d93 100644
--- a/src/libstrongswan/debug.h
+++ b/src/libstrongswan/debug.h
@@ -21,26 +21,95 @@
#ifndef DEBUG_H_
#define DEBUG_H_
+typedef enum debug_t debug_t;
+typedef enum level_t level_t;
+
#include <stdio.h>
+#include "enum.h"
+
+/**
+ * Debug message group.
+ */
+enum debug_t {
+ /** daemon specific */
+ DBG_DMN,
+ /** IKE_SA_MANAGER */
+ DBG_MGR,
+ /** IKE_SA */
+ DBG_IKE,
+ /** CHILD_SA */
+ DBG_CHD,
+ /** job processing */
+ DBG_JOB,
+ /** configuration backends */
+ DBG_CFG,
+ /** kernel interface */
+ DBG_KNL,
+ /** networking/sockets */
+ DBG_NET,
+ /** message encoding/decoding */
+ DBG_ENC,
+ /** libstrongswan */
+ DBG_LIB,
+ /** number of groups */
+ DBG_MAX,
+ /** pseudo group with all groups */
+ DBG_ANY = DBG_MAX,
+};
+
+/**
+ * short names of debug message group.
+ */
+extern enum_name_t *debug_names;
+
+/**
+ * short names of debug message group, lower case.
+ */
+extern enum_name_t *debug_lower_names;
+
+/**
+ * Debug levels used to control output verbosity.
+ */
+enum level_t {
+ /** absolutely silent */
+ LEVEL_SILENT = -1,
+ /** most important auditing logs */
+ LEVEL_AUDIT = 0,
+ /** control flow */
+ LEVEL_CTRL = 1,
+ /** diagnose problems */
+ LEVEL_DIAG = 2,
+ /** raw binary blobs */
+ LEVEL_RAW = 3,
+ /** including sensitive data (private keys) */
+ LEVEL_PRIVATE = 4,
+};
+
#ifndef DEBUG_LEVEL
# define DEBUG_LEVEL 4
#endif /* DEBUG_LEVEL */
/** debug macros, they call the dbg function hook */
+#if DEBUG_LEVEL >= 0
+# define DBG0(group, fmt, ...) dbg(group, 0, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
#if DEBUG_LEVEL >= 1
-# define DBG1(fmt, ...) dbg(1, fmt, ##__VA_ARGS__)
+# define DBG1(group, fmt, ...) dbg(group, 1, fmt, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL */
#if DEBUG_LEVEL >= 2
-# define DBG2(fmt, ...) dbg(2, fmt, ##__VA_ARGS__)
+# define DBG2(group, fmt, ...) dbg(group, 2, fmt, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL */
#if DEBUG_LEVEL >= 3
-# define DBG3(fmt, ...) dbg(3, fmt, ##__VA_ARGS__)
+# define DBG3(group, fmt, ...) dbg(group, 3, fmt, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL */
#if DEBUG_LEVEL >= 4
-# define DBG4(fmt, ...) dbg(4, fmt, ##__VA_ARGS__)
+# define DBG4(group, fmt, ...) dbg(group, 4, fmt, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL */
+#ifndef DBG0
+# define DBG0(...) {}
+#endif
#ifndef DBG1
# define DBG1(...) {}
#endif
@@ -55,13 +124,13 @@
#endif
/** dbg function hook, uses dbg_default() by default */
-extern void (*dbg) (int level, char *fmt, ...);
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
/** default logging function */
-void dbg_default(int level, char *fmt, ...);
+void dbg_default(debug_t group, level_t level, char *fmt, ...);
/** set the level logged by dbg_default() */
-void dbg_default_set_level(int level);
+void dbg_default_set_level(level_t level);
/** set the stream logged by dbg_default() to */
void dbg_default_set_stream(FILE *stream);
diff --git a/src/libstrongswan/enum.h b/src/libstrongswan/enum.h
index 6b9fd7eaa..691f9f2bc 100644
--- a/src/libstrongswan/enum.h
+++ b/src/libstrongswan/enum.h
@@ -22,7 +22,7 @@
#ifndef ENUM_H_
#define ENUM_H_
-#include <printf_hook.h>
+#include "printf_hook.h"
typedef struct enum_name_t enum_name_t;
diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c
index b73bfacf6..c81de032c 100644
--- a/src/libstrongswan/fetcher/fetcher_manager.c
+++ b/src/libstrongswan/fetcher/fetcher_manager.c
@@ -134,7 +134,7 @@ static status_t fetch(private_fetcher_manager_t *this,
this->lock->unlock(this->lock);
if (!capable)
{
- DBG1("unable to fetch from %s, no capable fetcher found", url);
+ DBG1(DBG_LIB, "unable to fetch from %s, no capable fetcher found", url);
}
return status;
}
diff --git a/src/libstrongswan/integrity_checker.c b/src/libstrongswan/integrity_checker.c
index 51da4e725..c9cad44ae 100644
--- a/src/libstrongswan/integrity_checker.c
+++ b/src/libstrongswan/integrity_checker.c
@@ -26,8 +26,8 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <debug.h>
-#include <library.h>
+#include "debug.h"
+#include "library.h"
typedef struct private_integrity_checker_t private_integrity_checker_t;
@@ -72,13 +72,14 @@ static u_int32_t build_file(private_integrity_checker_t *this, char *file,
fd = open(file, O_RDONLY);
if (fd == -1)
{
- DBG1(" opening '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " opening '%s' failed: %s", file, strerror(errno));
return 0;
}
if (fstat(fd, &sb) == -1)
{
- DBG1(" getting file size of '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " getting file size of '%s' failed: %s", file,
+ strerror(errno));
close(fd);
return 0;
}
@@ -86,7 +87,7 @@ static u_int32_t build_file(private_integrity_checker_t *this, char *file,
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
- DBG1(" mapping '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " mapping '%s' failed: %s", file, strerror(errno));
close(fd);
return 0;
}
@@ -146,13 +147,13 @@ static u_int32_t build_segment(private_integrity_checker_t *this, void *sym,
if (dladdr(sym, &dli) == 0)
{
- DBG1(" unable to locate symbol: %s", dlerror());
+ DBG1(DBG_LIB, " unable to locate symbol: %s", dlerror());
return 0;
}
/* we reuse the Dl_info struct as in/out parameter */
if (!dl_iterate_phdr((void*)callback, &dli))
{
- DBG1(" executable section not found");
+ DBG1(DBG_LIB, " executable section not found");
return 0;
}
@@ -192,7 +193,7 @@ static bool check_file(private_integrity_checker_t *this,
cs = find_checksum(this, name);
if (!cs)
{
- DBG1(" '%s' file checksum not found", name);
+ DBG1(DBG_LIB, " '%s' file checksum not found", name);
return FALSE;
}
sum = build_file(this, file, &len);
@@ -202,17 +203,17 @@ static bool check_file(private_integrity_checker_t *this,
}
if (cs->file_len != len)
{
- DBG1(" invalid '%s' file size: %u bytes, expected %u bytes",
+ DBG1(DBG_LIB, " invalid '%s' file size: %u bytes, expected %u bytes",
name, len, cs->file_len);
return FALSE;
}
if (cs->file != sum)
{
- DBG1(" invalid '%s' file checksum: %08x, expected %08x",
+ DBG1(DBG_LIB, " invalid '%s' file checksum: %08x, expected %08x",
name, sum, cs->file);
return FALSE;
}
- DBG2(" valid '%s' file checksum: %08x", name, sum);
+ DBG2(DBG_LIB, " valid '%s' file checksum: %08x", name, sum);
return TRUE;
}
@@ -229,7 +230,7 @@ static bool check_segment(private_integrity_checker_t *this,
cs = find_checksum(this, name);
if (!cs)
{
- DBG1(" '%s' segment checksum not found", name);
+ DBG1(DBG_LIB, " '%s' segment checksum not found", name);
return FALSE;
}
sum = build_segment(this, sym, &len);
@@ -239,17 +240,17 @@ static bool check_segment(private_integrity_checker_t *this,
}
if (cs->segment_len != len)
{
- DBG1(" invalid '%s' segment size: %u bytes, expected %u bytes",
- name, len, cs->segment_len);
+ DBG1(DBG_LIB, " invalid '%s' segment size: %u bytes,"
+ " expected %u bytes", name, len, cs->segment_len);
return FALSE;
}
if (cs->segment != sum)
{
- DBG1(" invalid '%s' segment checksum: %08x, expected %08x",
+ DBG1(DBG_LIB, " invalid '%s' segment checksum: %08x, expected %08x",
name, sum, cs->segment);
return FALSE;
}
- DBG2(" valid '%s' segment checksum: %08x", name, sum);
+ DBG2(DBG_LIB, " valid '%s' segment checksum: %08x", name, sum);
return TRUE;
}
@@ -262,7 +263,7 @@ static bool check(private_integrity_checker_t *this, char *name, void *sym)
if (dladdr(sym, &dli) == 0)
{
- DBG1("unable to locate symbol: %s", dlerror());
+ DBG1(DBG_LIB, "unable to locate symbol: %s", dlerror());
return FALSE;
}
if (!check_file(this, name, (char*)dli.dli_fname))
@@ -319,12 +320,14 @@ integrity_checker_t *integrity_checker_create(char *checksum_library)
}
else
{
- DBG1("checksum library '%s' invalid", checksum_library);
+ DBG1(DBG_LIB, "checksum library '%s' invalid",
+ checksum_library);
}
}
else
{
- DBG1("loading checksum library '%s' failed", checksum_library);
+ DBG1(DBG_LIB, "loading checksum library '%s' failed",
+ checksum_library);
}
}
return &this->public;
diff --git a/src/libstrongswan/integrity_checker.h b/src/libstrongswan/integrity_checker.h
index 7349353f3..55a4658f7 100644
--- a/src/libstrongswan/integrity_checker.h
+++ b/src/libstrongswan/integrity_checker.h
@@ -21,8 +21,8 @@
#ifndef INTEGRITY_CHECKER_H_
#define INTEGRITY_CHECKER_H_
-#include <utils.h>
-#include <plugins/plugin.h>
+#include "utils.h"
+#include "plugins/plugin.h"
typedef struct integrity_checker_t integrity_checker_t;
typedef struct integrity_checksum_t integrity_checksum_t;
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index 4e8bb87d0..108ac2ca0 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -18,14 +18,12 @@
#include <stdlib.h>
-#include <utils.h>
-#include <chunk.h>
-#include <debug.h>
-#include <threading/thread.h>
-#include <utils/identification.h>
-#include <utils/host.h>
+#include "debug.h"
+#include "threading/thread.h"
+#include "utils/identification.h"
+#include "utils/host.h"
#ifdef LEAK_DETECTIVE
-#include <utils/leak_detective.h>
+#include "utils/leak_detective.h"
#endif
#define CHECKSUM_LIBRARY IPSEC_DIR"/libchecksum.so"
@@ -68,7 +66,6 @@ void library_deinit()
this->public.encoding->destroy(this->public.encoding);
this->public.crypto->destroy(this->public.crypto);
this->public.fetcher->destroy(this->public.fetcher);
- this->public.attributes->destroy(this->public.attributes);
this->public.db->destroy(this->public.db);
this->public.printf_hook->destroy(this->public.printf_hook);
if (this->public.integrity)
@@ -133,7 +130,6 @@ bool library_init(char *settings)
this->public.creds = credential_factory_create();
this->public.encoding = key_encoding_create();
this->public.fetcher = fetcher_manager_create();
- this->public.attributes = attribute_manager_create();
this->public.db = database_factory_create();
this->public.plugins = plugin_loader_create();
this->public.integrity = NULL;
@@ -145,11 +141,11 @@ bool library_init(char *settings)
this->public.integrity = integrity_checker_create(CHECKSUM_LIBRARY);
if (!lib->integrity->check(lib->integrity, "libstrongswan", library_init))
{
- DBG1("integrity check of libstrongswan failed");
+ DBG1(DBG_LIB, "integrity check of libstrongswan failed");
return FALSE;
}
#else /* !INTEGRITY_TEST */
- DBG1("integrity test enabled, but not supported");
+ DBG1(DBG_LIB, "integrity test enabled, but not supported");
return FALSE;
#endif /* INTEGRITY_TEST */
}
diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h
index 78a6fe0a9..241084155 100644
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
@@ -55,18 +55,17 @@
#ifndef LIBRARY_H_
#define LIBRARY_H_
-#include <printf_hook.h>
-#include <utils.h>
-#include <chunk.h>
-#include <settings.h>
-#include <integrity_checker.h>
-#include <plugins/plugin_loader.h>
-#include <crypto/crypto_factory.h>
-#include <fetcher/fetcher_manager.h>
-#include <attributes/attribute_manager.h>
-#include <database/database_factory.h>
-#include <credentials/credential_factory.h>
-#include <credentials/keys/key_encoding.h>
+#include "printf_hook.h"
+#include "utils.h"
+#include "chunk.h"
+#include "settings.h"
+#include "integrity_checker.h"
+#include "plugins/plugin_loader.h"
+#include "crypto/crypto_factory.h"
+#include "fetcher/fetcher_manager.h"
+#include "database/database_factory.h"
+#include "credentials/credential_factory.h"
+#include "credentials/keys/key_encoding.h"
typedef struct library_t library_t;
@@ -101,11 +100,6 @@ struct library_t {
fetcher_manager_t *fetcher;
/**
- * manager for payload attributes
- */
- attribute_manager_t *attributes;
-
- /**
* database construction factory
*/
database_factory_t *db;
diff --git a/src/libstrongswan/plugins/aes/Makefile.am b/src/libstrongswan/plugins/aes/Makefile.am
index a3101172f..e72daeb44 100644
--- a/src/libstrongswan/plugins/aes/Makefile.am
+++ b/src/libstrongswan/plugins/aes/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-aes.la
+else
plugin_LTLIBRARIES = libstrongswan-aes.la
+endif
-libstrongswan_aes_la_SOURCES = aes_plugin.h aes_plugin.c aes_crypter.c aes_crypter.h
-libstrongswan_aes_la_LDFLAGS = -module -avoid-version
+libstrongswan_aes_la_SOURCES = \
+ aes_plugin.h aes_plugin.c aes_crypter.c aes_crypter.h
+libstrongswan_aes_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in
index 03ef465e0..391d23049 100644
--- a/src/libstrongswan/plugins/aes/Makefile.in
+++ b/src/libstrongswan/plugins/aes/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_aes_la_LIBADD =
am_libstrongswan_aes_la_OBJECTS = aes_plugin.lo aes_crypter.lo
libstrongswan_aes_la_OBJECTS = $(am_libstrongswan_aes_la_OBJECTS)
libstrongswan_aes_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_aes_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_aes_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_aes_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-aes.la
-libstrongswan_aes_la_SOURCES = aes_plugin.h aes_plugin.c aes_crypter.c aes_crypter.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-aes.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-aes.la
+libstrongswan_aes_la_SOURCES = \
+ aes_plugin.h aes_plugin.c aes_crypter.c aes_crypter.h
+
libstrongswan_aes_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -290,6 +296,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -322,7 +337,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-aes.la: $(libstrongswan_aes_la_OBJECTS) $(libstrongswan_aes_la_DEPENDENCIES)
- $(libstrongswan_aes_la_LINK) -rpath $(plugindir) $(libstrongswan_aes_la_OBJECTS) $(libstrongswan_aes_la_LIBADD) $(LIBS)
+ $(libstrongswan_aes_la_LINK) $(am_libstrongswan_aes_la_rpath) $(libstrongswan_aes_la_OBJECTS) $(libstrongswan_aes_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -476,8 +491,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -548,18 +563,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/aes/aes_plugin.c b/src/libstrongswan/plugins/aes/aes_plugin.c
index c6215cc7f..1e920f8cc 100644
--- a/src/libstrongswan/plugins/aes/aes_plugin.c
+++ b/src/libstrongswan/plugins/aes/aes_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_aes_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *aes_plugin_create()
{
private_aes_plugin_t *this = malloc_thing(private_aes_plugin_t);
diff --git a/src/libstrongswan/plugins/aes/aes_plugin.h b/src/libstrongswan/plugins/aes/aes_plugin.h
index a6ff620ed..f0f0e8154 100644
--- a/src/libstrongswan/plugins/aes/aes_plugin.h
+++ b/src/libstrongswan/plugins/aes/aes_plugin.h
@@ -39,9 +39,4 @@ struct aes_plugin_t {
plugin_t plugin;
};
-/**
- * Create a aes_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** AES_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/agent/Makefile.am b/src/libstrongswan/plugins/agent/Makefile.am
index e1000e562..ffa6e8b7f 100644
--- a/src/libstrongswan/plugins/agent/Makefile.am
+++ b/src/libstrongswan/plugins/agent/Makefile.am
@@ -3,10 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-agent.la
+else
plugin_LTLIBRARIES = libstrongswan-agent.la
+endif
-libstrongswan_agent_la_SOURCES = agent_plugin.h agent_plugin.c \
- agent_private_key.c agent_private_key.h
+libstrongswan_agent_la_SOURCES = \
+ agent_plugin.h agent_plugin.c \
+ agent_private_key.c agent_private_key.h
libstrongswan_agent_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in
index 5bf52aa56..bd6465374 100644
--- a/src/libstrongswan/plugins/agent/Makefile.in
+++ b/src/libstrongswan/plugins/agent/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_agent_la_LIBADD =
am_libstrongswan_agent_la_OBJECTS = agent_plugin.lo \
agent_private_key.lo
@@ -80,6 +80,9 @@ libstrongswan_agent_la_OBJECTS = $(am_libstrongswan_agent_la_OBJECTS)
libstrongswan_agent_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_agent_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_agent_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_agent_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,9 +258,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-agent.la
-libstrongswan_agent_la_SOURCES = agent_plugin.h agent_plugin.c \
- agent_private_key.c agent_private_key.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-agent.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-agent.la
+libstrongswan_agent_la_SOURCES = \
+ agent_plugin.h agent_plugin.c \
+ agent_private_key.c agent_private_key.h
libstrongswan_agent_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -293,6 +299,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -325,7 +340,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-agent.la: $(libstrongswan_agent_la_OBJECTS) $(libstrongswan_agent_la_DEPENDENCIES)
- $(libstrongswan_agent_la_LINK) -rpath $(plugindir) $(libstrongswan_agent_la_OBJECTS) $(libstrongswan_agent_la_LIBADD) $(LIBS)
+ $(libstrongswan_agent_la_LINK) $(am_libstrongswan_agent_la_rpath) $(libstrongswan_agent_la_OBJECTS) $(libstrongswan_agent_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -479,8 +494,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -551,18 +566,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/agent/agent_plugin.c b/src/libstrongswan/plugins/agent/agent_plugin.c
index 299b2cc1d..d40b437bb 100644
--- a/src/libstrongswan/plugins/agent/agent_plugin.c
+++ b/src/libstrongswan/plugins/agent/agent_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_agent_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *agent_plugin_create()
{
private_agent_plugin_t *this = malloc_thing(private_agent_plugin_t);
diff --git a/src/libstrongswan/plugins/agent/agent_plugin.h b/src/libstrongswan/plugins/agent/agent_plugin.h
index e49af42d8..d352c305c 100644
--- a/src/libstrongswan/plugins/agent/agent_plugin.h
+++ b/src/libstrongswan/plugins/agent/agent_plugin.h
@@ -39,9 +39,4 @@ struct agent_plugin_t {
plugin_t plugin;
};
-/**
- * Create a agent_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** AGENT_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c
index d0a2da87f..4247f849e 100644
--- a/src/libstrongswan/plugins/agent/agent_private_key.c
+++ b/src/libstrongswan/plugins/agent/agent_private_key.c
@@ -137,7 +137,8 @@ static int open_connection(char *path)
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1)
{
- DBG1("opening ssh-agent socket %s failed: %s:", path, strerror(errno));
+ DBG1(DBG_LIB, "opening ssh-agent socket %s failed: %s:", path,
+ strerror(errno));
return -1;
}
@@ -147,7 +148,8 @@ static int open_connection(char *path)
if (connect(s, (struct sockaddr*)&addr, SUN_LEN(&addr)) != 0)
{
- DBG1("connecting to ssh-agent socket failed: %s", strerror(errno));
+ DBG1(DBG_LIB, "connecting to ssh-agent socket failed: %s",
+ strerror(errno));
close(s);
return -1;
}
@@ -168,7 +170,7 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
write(this->socket, &buf, 1) != 1)
{
- DBG1("writing to ssh-agent failed");
+ DBG1(DBG_LIB, "writing to ssh-agent failed");
return FALSE;
}
@@ -179,7 +181,7 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
read_uint32(&blob) != blob.len ||
read_byte(&blob) != SSH_AGENT_ID_RESPONSE)
{
- DBG1("received invalid ssh-agent identity response");
+ DBG1(DBG_LIB, "received invalid ssh-agent identity response");
return FALSE;
}
count = read_uint32(&blob);
@@ -231,7 +233,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
if (scheme != SIGN_RSA_EMSA_PKCS1_SHA1)
{
- DBG1("signature scheme %N not supported by ssh-agent",
+ DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent",
signature_scheme_names, scheme);
return FALSE;
}
@@ -241,7 +243,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
write(this->socket, &buf, 1) != 1)
{
- DBG1("writing to ssh-agent failed");
+ DBG1(DBG_LIB, "writing to ssh-agent failed");
return FALSE;
}
@@ -249,7 +251,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
write(this->socket, this->key.ptr, this->key.len) != this->key.len)
{
- DBG1("writing to ssh-agent failed");
+ DBG1(DBG_LIB, "writing to ssh-agent failed");
return FALSE;
}
@@ -257,14 +259,14 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
write(this->socket, data.ptr, data.len) != data.len)
{
- DBG1("writing to ssh-agent failed");
+ DBG1(DBG_LIB, "writing to ssh-agent failed");
return FALSE;
}
flags = htonl(0);
if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags))
{
- DBG1("writing to ssh-agent failed");
+ DBG1(DBG_LIB, "writing to ssh-agent failed");
return FALSE;
}
@@ -274,7 +276,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
read_uint32(&blob) != blob.len ||
read_byte(&blob) != SSH_AGENT_SIGN_RESPONSE)
{
- DBG1("received invalid ssh-agent signature response");
+ DBG1(DBG_LIB, "received invalid ssh-agent signature response");
return FALSE;
}
/* parse length */
@@ -285,7 +287,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
blob = read_string(&blob);
if (!blob.len)
{
- DBG1("received invalid ssh-agent signature response");
+ DBG1(DBG_LIB, "received invalid ssh-agent signature response");
return FALSE;
}
*signature = chunk_clone(blob);
@@ -306,7 +308,7 @@ static key_type_t get_type(private_agent_private_key_t *this)
static bool decrypt(private_agent_private_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("private key decryption not supported by ssh-agent");
+ DBG1(DBG_LIB, "private key decryption not supported by ssh-agent");
return FALSE;
}
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.am b/src/libstrongswan/plugins/blowfish/Makefile.am
index de8948445..95c414204 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.am
+++ b/src/libstrongswan/plugins/blowfish/Makefile.am
@@ -3,10 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-blowfish.la
+else
plugin_LTLIBRARIES = libstrongswan-blowfish.la
+endif
libstrongswan_blowfish_la_SOURCES = \
-blowfish_plugin.h blowfish_plugin.c blowfish_crypter.c blowfish_crypter.h \
-bf_skey.c blowfish.h bf_pi.h bf_locl.h bf_enc.c
-libstrongswan_blowfish_la_LDFLAGS = -module -avoid-version
+ blowfish_plugin.h blowfish_plugin.c blowfish_crypter.c blowfish_crypter.h \
+ bf_skey.c blowfish.h bf_pi.h bf_locl.h bf_enc.c
+libstrongswan_blowfish_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in
index 7b55d69c7..f95a4abe5 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.in
+++ b/src/libstrongswan/plugins/blowfish/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_blowfish_la_LIBADD =
am_libstrongswan_blowfish_la_OBJECTS = blowfish_plugin.lo \
blowfish_crypter.lo bf_skey.lo bf_enc.lo
@@ -82,6 +82,9 @@ libstrongswan_blowfish_la_LINK = $(LIBTOOL) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_blowfish_la_LDFLAGS) \
$(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_blowfish_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_blowfish_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -220,6 +223,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -256,10 +260,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-blowfish.la
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-blowfish.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-blowfish.la
libstrongswan_blowfish_la_SOURCES = \
-blowfish_plugin.h blowfish_plugin.c blowfish_crypter.c blowfish_crypter.h \
-bf_skey.c blowfish.h bf_pi.h bf_locl.h bf_enc.c
+ blowfish_plugin.h blowfish_plugin.c blowfish_crypter.c blowfish_crypter.h \
+ bf_skey.c blowfish.h bf_pi.h bf_locl.h bf_enc.c
libstrongswan_blowfish_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -296,6 +301,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -328,7 +342,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-blowfish.la: $(libstrongswan_blowfish_la_OBJECTS) $(libstrongswan_blowfish_la_DEPENDENCIES)
- $(libstrongswan_blowfish_la_LINK) -rpath $(plugindir) $(libstrongswan_blowfish_la_OBJECTS) $(libstrongswan_blowfish_la_LIBADD) $(LIBS)
+ $(libstrongswan_blowfish_la_LINK) $(am_libstrongswan_blowfish_la_rpath) $(libstrongswan_blowfish_la_OBJECTS) $(libstrongswan_blowfish_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -484,8 +498,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -556,18 +570,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c
index 993dc8b3b..f9fb605b3 100644
--- a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c
+++ b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c
@@ -45,7 +45,7 @@ static void destroy(private_blowfish_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *blowfish_plugin_create()
{
private_blowfish_plugin_t *this = malloc_thing(private_blowfish_plugin_t);
diff --git a/src/libstrongswan/plugins/blowfish/blowfish_plugin.h b/src/libstrongswan/plugins/blowfish/blowfish_plugin.h
index 596a7c791..6a87f42ee 100644
--- a/src/libstrongswan/plugins/blowfish/blowfish_plugin.h
+++ b/src/libstrongswan/plugins/blowfish/blowfish_plugin.h
@@ -40,9 +40,4 @@ struct blowfish_plugin_t {
plugin_t plugin;
};
-/**
- * Create a blowfish_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** BLOWFISH_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/curl/Makefile.am b/src/libstrongswan/plugins/curl/Makefile.am
index f0a41e4ad..43718f678 100644
--- a/src/libstrongswan/plugins/curl/Makefile.am
+++ b/src/libstrongswan/plugins/curl/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-curl.la
+else
plugin_LTLIBRARIES = libstrongswan-curl.la
+endif
+
+libstrongswan_curl_la_SOURCES = \
+ curl_plugin.h curl_plugin.c curl_fetcher.c curl_fetcher.h
-libstrongswan_curl_la_SOURCES = curl_plugin.h curl_plugin.c curl_fetcher.c curl_fetcher.h
libstrongswan_curl_la_LDFLAGS = -module -avoid-version
libstrongswan_curl_la_LIBADD = -lcurl
-
diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in
index 32b2504fe..1952b22e7 100644
--- a/src/libstrongswan/plugins/curl/Makefile.in
+++ b/src/libstrongswan/plugins/curl/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_curl_la_DEPENDENCIES =
am_libstrongswan_curl_la_OBJECTS = curl_plugin.lo curl_fetcher.lo
libstrongswan_curl_la_OBJECTS = $(am_libstrongswan_curl_la_OBJECTS)
libstrongswan_curl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_curl_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_curl_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_curl_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-curl.la
-libstrongswan_curl_la_SOURCES = curl_plugin.h curl_plugin.c curl_fetcher.c curl_fetcher.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-curl.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-curl.la
+libstrongswan_curl_la_SOURCES = \
+ curl_plugin.h curl_plugin.c curl_fetcher.c curl_fetcher.h
+
libstrongswan_curl_la_LDFLAGS = -module -avoid-version
libstrongswan_curl_la_LIBADD = -lcurl
all: all-am
@@ -291,6 +297,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -323,7 +338,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-curl.la: $(libstrongswan_curl_la_OBJECTS) $(libstrongswan_curl_la_DEPENDENCIES)
- $(libstrongswan_curl_la_LINK) -rpath $(plugindir) $(libstrongswan_curl_la_OBJECTS) $(libstrongswan_curl_la_LIBADD) $(LIBS)
+ $(libstrongswan_curl_la_LINK) $(am_libstrongswan_curl_la_rpath) $(libstrongswan_curl_la_OBJECTS) $(libstrongswan_curl_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -477,8 +492,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -549,18 +564,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c
index 08315e932..2341c9052 100644
--- a/src/libstrongswan/plugins/curl/curl_fetcher.c
+++ b/src/libstrongswan/plugins/curl/curl_fetcher.c
@@ -84,7 +84,7 @@ METHOD(fetcher_t, fetch, status_t,
curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, this->headers);
}
- DBG2(" sending http request to '%s'...", uri);
+ DBG2(DBG_LIB, " sending http request to '%s'...", uri);
switch (curl_easy_perform(this->curl))
{
case CURLE_UNSUPPORTED_PROTOCOL:
@@ -94,7 +94,7 @@ METHOD(fetcher_t, fetch, status_t,
status = SUCCESS;
break;
default:
- DBG1("libcurl http request failed: %s", error);
+ DBG1(DBG_LIB, "libcurl http request failed: %s", error);
status = FAILED;
break;
}
diff --git a/src/libstrongswan/plugins/curl/curl_plugin.c b/src/libstrongswan/plugins/curl/curl_plugin.c
index 13dfa053f..e00fcfc03 100644
--- a/src/libstrongswan/plugins/curl/curl_plugin.c
+++ b/src/libstrongswan/plugins/curl/curl_plugin.c
@@ -48,7 +48,7 @@ static void destroy(private_curl_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *curl_plugin_create()
{
CURLcode res;
private_curl_plugin_t *this = malloc_thing(private_curl_plugin_t);
@@ -69,7 +69,7 @@ plugin_t *plugin_create()
}
else
{
- DBG1("global libcurl initializing failed: %s, curl disabled",
+ DBG1(DBG_LIB, "global libcurl initializing failed: %s, curl disabled",
curl_easy_strerror(res));
}
return &this->public.plugin;
diff --git a/src/libstrongswan/plugins/curl/curl_plugin.h b/src/libstrongswan/plugins/curl/curl_plugin.h
index 1b748446b..ae17285c2 100644
--- a/src/libstrongswan/plugins/curl/curl_plugin.h
+++ b/src/libstrongswan/plugins/curl/curl_plugin.h
@@ -39,9 +39,4 @@ struct curl_plugin_t {
plugin_t plugin;
};
-/**
- * Create a curl_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** CURL_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/des/Makefile.am b/src/libstrongswan/plugins/des/Makefile.am
index 76cfbc419..c7d9ce915 100644
--- a/src/libstrongswan/plugins/des/Makefile.am
+++ b/src/libstrongswan/plugins/des/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-des.la
+else
plugin_LTLIBRARIES = libstrongswan-des.la
+endif
-libstrongswan_des_la_SOURCES = des_plugin.h des_plugin.c des_crypter.c des_crypter.h
-libstrongswan_des_la_LDFLAGS = -module -avoid-version
+libstrongswan_des_la_SOURCES = \
+ des_plugin.h des_plugin.c des_crypter.c des_crypter.h
+libstrongswan_des_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in
index f68b4bd03..af351cfe3 100644
--- a/src/libstrongswan/plugins/des/Makefile.in
+++ b/src/libstrongswan/plugins/des/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_des_la_LIBADD =
am_libstrongswan_des_la_OBJECTS = des_plugin.lo des_crypter.lo
libstrongswan_des_la_OBJECTS = $(am_libstrongswan_des_la_OBJECTS)
libstrongswan_des_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_des_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_des_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_des_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-des.la
-libstrongswan_des_la_SOURCES = des_plugin.h des_plugin.c des_crypter.c des_crypter.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-des.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-des.la
+libstrongswan_des_la_SOURCES = \
+ des_plugin.h des_plugin.c des_crypter.c des_crypter.h
+
libstrongswan_des_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -290,6 +296,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -322,7 +337,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-des.la: $(libstrongswan_des_la_OBJECTS) $(libstrongswan_des_la_DEPENDENCIES)
- $(libstrongswan_des_la_LINK) -rpath $(plugindir) $(libstrongswan_des_la_OBJECTS) $(libstrongswan_des_la_LIBADD) $(LIBS)
+ $(libstrongswan_des_la_LINK) $(am_libstrongswan_des_la_rpath) $(libstrongswan_des_la_OBJECTS) $(libstrongswan_des_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -476,8 +491,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -548,18 +563,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/des/des_plugin.c b/src/libstrongswan/plugins/des/des_plugin.c
index 649d224ab..afc82e8d4 100644
--- a/src/libstrongswan/plugins/des/des_plugin.c
+++ b/src/libstrongswan/plugins/des/des_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_des_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *des_plugin_create()
{
private_des_plugin_t *this = malloc_thing(private_des_plugin_t);
diff --git a/src/libstrongswan/plugins/des/des_plugin.h b/src/libstrongswan/plugins/des/des_plugin.h
index 17df220bc..cfff420c0 100644
--- a/src/libstrongswan/plugins/des/des_plugin.h
+++ b/src/libstrongswan/plugins/des/des_plugin.h
@@ -39,9 +39,4 @@ struct des_plugin_t {
plugin_t plugin;
};
-/**
- * Create a des_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** DES_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.am b/src/libstrongswan/plugins/dnskey/Makefile.am
index fd020f505..fbba95e0a 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.am
+++ b/src/libstrongswan/plugins/dnskey/Makefile.am
@@ -3,10 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-dnskey.la
+else
plugin_LTLIBRARIES = libstrongswan-dnskey.la
+endif
-libstrongswan_dnskey_la_SOURCES = dnskey_plugin.h dnskey_plugin.c \
- dnskey_builder.h dnskey_builder.c
+libstrongswan_dnskey_la_SOURCES = \
+ dnskey_plugin.h dnskey_plugin.c \
+ dnskey_builder.h dnskey_builder.c
libstrongswan_dnskey_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in
index d7d5ff29b..1f1f90127 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.in
+++ b/src/libstrongswan/plugins/dnskey/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_dnskey_la_LIBADD =
am_libstrongswan_dnskey_la_OBJECTS = dnskey_plugin.lo \
dnskey_builder.lo
@@ -81,6 +81,9 @@ libstrongswan_dnskey_la_OBJECTS = \
libstrongswan_dnskey_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_dnskey_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_dnskey_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_dnskey_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -219,6 +222,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -255,9 +259,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-dnskey.la
-libstrongswan_dnskey_la_SOURCES = dnskey_plugin.h dnskey_plugin.c \
- dnskey_builder.h dnskey_builder.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-dnskey.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-dnskey.la
+libstrongswan_dnskey_la_SOURCES = \
+ dnskey_plugin.h dnskey_plugin.c \
+ dnskey_builder.h dnskey_builder.c
libstrongswan_dnskey_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -294,6 +300,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -326,7 +341,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-dnskey.la: $(libstrongswan_dnskey_la_OBJECTS) $(libstrongswan_dnskey_la_DEPENDENCIES)
- $(libstrongswan_dnskey_la_LINK) -rpath $(plugindir) $(libstrongswan_dnskey_la_OBJECTS) $(libstrongswan_dnskey_la_LIBADD) $(LIBS)
+ $(libstrongswan_dnskey_la_LINK) $(am_libstrongswan_dnskey_la_rpath) $(libstrongswan_dnskey_la_OBJECTS) $(libstrongswan_dnskey_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -480,8 +495,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -552,18 +567,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/dnskey/dnskey_builder.c b/src/libstrongswan/plugins/dnskey/dnskey_builder.c
index ba20e7158..ea4eb6cda 100644
--- a/src/libstrongswan/plugins/dnskey/dnskey_builder.c
+++ b/src/libstrongswan/plugins/dnskey/dnskey_builder.c
@@ -52,7 +52,7 @@ static dnskey_public_key_t *parse_public_key(chunk_t blob)
if (blob.len < sizeof(dnskey_rr_t))
{
- DBG1("DNSKEY too short");
+ DBG1(DBG_LIB, "DNSKEY too short");
return NULL;
}
blob = chunk_skip(blob, sizeof(dnskey_rr_t));
@@ -63,7 +63,8 @@ static dnskey_public_key_t *parse_public_key(chunk_t blob)
return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
BUILD_BLOB_DNSKEY, blob, BUILD_END);
default:
- DBG1("DNSKEY public key algorithm %d not supported", rr->algorithm);
+ DBG1(DBG_LIB, "DNSKEY public key algorithm %d not supported",
+ rr->algorithm);
return NULL;
}
}
@@ -77,7 +78,7 @@ static dnskey_public_key_t *parse_rsa_public_key(chunk_t blob)
if (blob.len < 3)
{
- DBG1("RFC 3110 public key blob too short for exponent length");
+ DBG1(DBG_LIB, "RFC 3110 public key blob too short for exponent length");
return NULL;
}
@@ -94,7 +95,7 @@ static dnskey_public_key_t *parse_rsa_public_key(chunk_t blob)
e.ptr = blob.ptr;
if (e.len >= blob.len)
{
- DBG1("RFC 3110 public key blob too short for exponent");
+ DBG1(DBG_LIB, "RFC 3110 public key blob too short for exponent");
return NULL;
}
n = chunk_skip(blob, e.len);
diff --git a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c
index 83dbe31a1..125047b05 100644
--- a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c
+++ b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_dnskey_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *dnskey_plugin_create()
{
private_dnskey_plugin_t *this = malloc_thing(private_dnskey_plugin_t);
diff --git a/src/libstrongswan/plugins/dnskey/dnskey_plugin.h b/src/libstrongswan/plugins/dnskey/dnskey_plugin.h
index 17790e1c6..8b49bd6cb 100644
--- a/src/libstrongswan/plugins/dnskey/dnskey_plugin.h
+++ b/src/libstrongswan/plugins/dnskey/dnskey_plugin.h
@@ -39,9 +39,4 @@ struct dnskey_plugin_t {
plugin_t plugin;
};
-/**
- * Create a dnskey_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** DNSKEY_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.am b/src/libstrongswan/plugins/fips_prf/Makefile.am
index d9431947e..c9cf2c977 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.am
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-fips-prf.la
+else
plugin_LTLIBRARIES = libstrongswan-fips-prf.la
+endif
-libstrongswan_fips_prf_la_SOURCES = fips_prf_plugin.h fips_prf_plugin.c fips_prf.c fips_prf.h
-libstrongswan_fips_prf_la_LDFLAGS = -module -avoid-version
+libstrongswan_fips_prf_la_SOURCES = \
+ fips_prf_plugin.h fips_prf_plugin.c fips_prf.c fips_prf.h
+libstrongswan_fips_prf_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in
index b23af6def..70553fbd8 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.in
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_fips_prf_la_LIBADD =
am_libstrongswan_fips_prf_la_OBJECTS = fips_prf_plugin.lo fips_prf.lo
libstrongswan_fips_prf_la_OBJECTS = \
@@ -81,6 +81,9 @@ libstrongswan_fips_prf_la_LINK = $(LIBTOOL) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_fips_prf_la_LDFLAGS) \
$(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_fips_prf_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_fips_prf_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -219,6 +222,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -255,8 +259,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-fips-prf.la
-libstrongswan_fips_prf_la_SOURCES = fips_prf_plugin.h fips_prf_plugin.c fips_prf.c fips_prf.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-fips-prf.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-fips-prf.la
+libstrongswan_fips_prf_la_SOURCES = \
+ fips_prf_plugin.h fips_prf_plugin.c fips_prf.c fips_prf.h
+
libstrongswan_fips_prf_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -292,6 +299,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -324,7 +340,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-fips-prf.la: $(libstrongswan_fips_prf_la_OBJECTS) $(libstrongswan_fips_prf_la_DEPENDENCIES)
- $(libstrongswan_fips_prf_la_LINK) -rpath $(plugindir) $(libstrongswan_fips_prf_la_OBJECTS) $(libstrongswan_fips_prf_la_LIBADD) $(LIBS)
+ $(libstrongswan_fips_prf_la_LINK) $(am_libstrongswan_fips_prf_la_rpath) $(libstrongswan_fips_prf_la_OBJECTS) $(libstrongswan_fips_prf_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -478,8 +494,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -550,18 +566,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c
index 123d2a244..ad03fa585 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf.c
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c
@@ -126,14 +126,14 @@ static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[])
{
/* a. XVAL = (XKEY + XSEED j) mod 2^b */
add_mod(this->b, xkey, xseed, xval);
- DBG3("XVAL %b", xval, this->b);
+ DBG3(DBG_LIB, "XVAL %b", xval, this->b);
/* b. wi = G(t, XVAL ) */
this->g(this, chunk_create(xval, this->b), &w[i * this->b]);
- DBG3("w[%d] %b", i, &w[i * this->b], this->b);
+ DBG3(DBG_LIB, "w[%d] %b", i, &w[i * this->b], this->b);
/* c. XKEY = (1 + XKEY + wi) mod 2b */
add_mod(this->b, xkey, &w[i * this->b], sum);
add_mod(this->b, sum, one, xkey);
- DBG3("XKEY %b", xkey, this->b);
+ DBG3(DBG_LIB, "XKEY %b", xkey, this->b);
}
/* 3.3 done already, mod q not used */
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c
index 6c0842f81..f41265637 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_fips_prf_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *fips_prf_plugin_create()
{
private_fips_prf_plugin_t *this = malloc_thing(private_fips_prf_plugin_t);
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.h b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.h
index 8d65254ba..3bd26ad45 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.h
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.h
@@ -39,9 +39,4 @@ struct fips_prf_plugin_t {
plugin_t plugin;
};
-/**
- * Create a fips_prf_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** FIPS_PRF_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.am b/src/libstrongswan/plugins/gcrypt/Makefile.am
index a468a5ed9..48bf916ab 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.am
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-gcrypt.la
+else
plugin_LTLIBRARIES = libstrongswan-gcrypt.la
+endif
-libstrongswan_gcrypt_la_SOURCES = gcrypt_plugin.h gcrypt_plugin.c \
+libstrongswan_gcrypt_la_SOURCES = \
+ gcrypt_plugin.h gcrypt_plugin.c \
gcrypt_rsa_public_key.h gcrypt_rsa_public_key.c \
gcrypt_rsa_private_key.h gcrypt_rsa_private_key.c \
gcrypt_dh.h gcrypt_dh.c \
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in
index c3081e2dd..35829c950 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.in
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_gcrypt_la_DEPENDENCIES =
am_libstrongswan_gcrypt_la_OBJECTS = gcrypt_plugin.lo \
gcrypt_rsa_public_key.lo gcrypt_rsa_private_key.lo \
@@ -82,6 +82,9 @@ libstrongswan_gcrypt_la_OBJECTS = \
libstrongswan_gcrypt_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_gcrypt_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_gcrypt_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_gcrypt_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -220,6 +223,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -256,8 +260,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-gcrypt.la
-libstrongswan_gcrypt_la_SOURCES = gcrypt_plugin.h gcrypt_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-gcrypt.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-gcrypt.la
+libstrongswan_gcrypt_la_SOURCES = \
+ gcrypt_plugin.h gcrypt_plugin.c \
gcrypt_rsa_public_key.h gcrypt_rsa_public_key.c \
gcrypt_rsa_private_key.h gcrypt_rsa_private_key.c \
gcrypt_dh.h gcrypt_dh.c \
@@ -301,6 +307,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -333,7 +348,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-gcrypt.la: $(libstrongswan_gcrypt_la_OBJECTS) $(libstrongswan_gcrypt_la_DEPENDENCIES)
- $(libstrongswan_gcrypt_la_LINK) -rpath $(plugindir) $(libstrongswan_gcrypt_la_OBJECTS) $(libstrongswan_gcrypt_la_LIBADD) $(LIBS)
+ $(libstrongswan_gcrypt_la_LINK) $(am_libstrongswan_gcrypt_la_rpath) $(libstrongswan_gcrypt_la_OBJECTS) $(libstrongswan_gcrypt_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -492,8 +507,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -564,18 +579,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
index 1eee6226d..5dbdde32c 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
@@ -234,7 +234,7 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
if (err)
{
- DBG1("grcy_cipher_open(%N) failed: %s",
+ DBG1(DBG_LIB, "grcy_cipher_open(%N) failed: %s",
encryption_algorithm_names, algo, gpg_strerror(err));
free(this);
return NULL;
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
index 59c82f1e7..08d6239ad 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -19,310 +20,6 @@
#include <debug.h>
-/**
- * Modulus of Group 1 (MODP_768_BIT).
- */
-static u_int8_t group1_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 2 (MODP_1024_BIT).
- */
-static u_int8_t group2_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 5 (MODP_1536_BIT).
- */
-static u_int8_t group5_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-/**
- * Modulus of Group 14 (MODP_2048_BIT).
- */
-static u_int8_t group14_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 15 (MODP_3072_BIT).
- */
-static u_int8_t group15_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 16 (MODP_4096_BIT).
- */
-static u_int8_t group16_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 17 (MODP_6144_BIT).
- */
-static u_int8_t group17_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
- 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
- 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
- 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
- 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
- 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
- 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
- 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
- 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
- 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
- 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
- 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
- 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
- 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
- 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
- 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
- 0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 18 (MODP_8192_BIT).
- */
-static u_int8_t group18_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
- 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
- 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
- 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
- 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
- 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
- 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
- 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
- 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
- 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
- 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
- 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
- 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
- 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
- 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
- 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
- 0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
- 0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA,
- 0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,
- 0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
- 0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D,
- 0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,
- 0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
- 0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8,
- 0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,
- 0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
- 0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D,
- 0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,
- 0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
- 0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B,
- 0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,
- 0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
- 0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-};
-
-typedef struct modulus_entry_t modulus_entry_t;
-
-/**
- * Entry of the modulus list.
- */
-struct modulus_entry_t {
- /** IKEv2 DH group */
- diffie_hellman_group_t group;
- /** modulus */
- chunk_t modulus;
- /** optimum length of exponent in bytes */
- size_t opt_len;
- /** generator */
- u_int16_t g;
-};
-
-/**
- * All supported modulus values - optimum exponent size according to RFC 3526.
- */
-static modulus_entry_t modulus_entries[] = {
- {MODP_768_BIT, {group1_modulus, sizeof(group1_modulus)}, 32, 2},
- {MODP_1024_BIT, {group2_modulus, sizeof(group2_modulus)}, 32, 2},
- {MODP_1536_BIT, {group5_modulus, sizeof(group5_modulus)}, 32, 2},
- {MODP_2048_BIT, {group14_modulus, sizeof(group14_modulus)}, 48, 2},
- {MODP_3072_BIT, {group15_modulus, sizeof(group15_modulus)}, 48, 2},
- {MODP_4096_BIT, {group16_modulus, sizeof(group16_modulus)}, 64, 2},
- {MODP_6144_BIT, {group17_modulus, sizeof(group17_modulus)}, 64, 2},
- {MODP_8192_BIT, {group18_modulus, sizeof(group18_modulus)}, 64, 2},
-};
-
-/**
- * Lookup the modulus in modulo table
- */
-static modulus_entry_t *find_entry(diffie_hellman_group_t group)
-{
- int i;
-
- for (i = 0; i < countof(modulus_entries); i++)
- {
- if (modulus_entries[i].group == group)
- {
- return &modulus_entries[i];
- }
- }
- return NULL;
-}
-
typedef struct private_gcrypt_dh_t private_gcrypt_dh_t;
/**
@@ -392,7 +89,7 @@ static void set_other_public_value(private_gcrypt_dh_t *this, chunk_t value)
err = gcry_mpi_scan(&this->yb, GCRYMPI_FMT_USG, value.ptr, value.len, NULL);
if (err)
{
- DBG1("importing mpi yb failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "importing mpi yb failed: %s", gpg_strerror(err));
return;
}
@@ -413,7 +110,8 @@ static void set_other_public_value(private_gcrypt_dh_t *this, chunk_t value)
}
else
{
- DBG1("public DH value verification failed: y < 2 || y > p - 1 ");
+ DBG1(DBG_LIB, "public DH value verification failed:"
+ " y < 2 || y > p - 1 ");
}
gcry_mpi_release(p_min_1);
}
@@ -485,14 +183,13 @@ static void destroy(private_gcrypt_dh_t *this)
gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group)
{
private_gcrypt_dh_t *this;
- modulus_entry_t *entry;
+ diffie_hellman_params_t *params;
gcry_error_t err;
chunk_t random;
rng_t *rng;
- size_t len;
- entry = find_entry(group);
- if (!entry)
+ params = diffie_hellman_get_params(group);
+ if (!params)
{
return NULL;
}
@@ -506,53 +203,53 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group)
this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy;
this->group = group;
- this->p_len = entry->modulus.len;
+ this->p_len = params->prime.len;
err = gcry_mpi_scan(&this->p, GCRYMPI_FMT_USG,
- entry->modulus.ptr, entry->modulus.len, NULL);
+ params->prime.ptr, params->prime.len, NULL);
if (err)
{
- DBG1("importing mpi modulus failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "importing mpi modulus failed: %s", gpg_strerror(err));
free(this);
return NULL;
}
- if (lib->settings->get_int(lib->settings,
- "libstrongswan.dh_exponent_ansi_x9_42", TRUE))
- {
- len = this->p_len;
- }
- else
+ err = gcry_mpi_scan(&this->g, GCRYMPI_FMT_USG,
+ params->generator.ptr, params->generator.len, NULL);
+ if (err)
{
- len = entry->opt_len;
+ DBG1(DBG_LIB, "importing mpi generator failed: %s", gpg_strerror(err));
+ gcry_mpi_release(this->p);
+ free(this);
+ return NULL;
}
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (rng)
{ /* prefer external randomizer */
- rng->allocate_bytes(rng, len, &random);
+ rng->allocate_bytes(rng, params->exp_len, &random);
rng->destroy(rng);
err = gcry_mpi_scan(&this->xa, GCRYMPI_FMT_USG,
random.ptr, random.len, NULL);
chunk_clear(&random);
if (err)
{
- DBG1("importing mpi xa failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "importing mpi xa failed: %s", gpg_strerror(err));
gcry_mpi_release(this->p);
+ gcry_mpi_release(this->g);
free(this);
return NULL;
}
}
else
{ /* fallback to gcrypt internal randomizer, shouldn't ever happen */
- this->xa = gcry_mpi_new(len * 8);
- gcry_mpi_randomize(this->xa, len * 8, GCRY_STRONG_RANDOM);
+ this->xa = gcry_mpi_new(params->exp_len * 8);
+ gcry_mpi_randomize(this->xa, params->exp_len * 8, GCRY_STRONG_RANDOM);
}
- if (len == this->p_len)
+ if (params->exp_len == this->p_len)
{
/* achieve bitsof(p)-1 by setting MSB to 0 */
- gcry_mpi_clear_bit(this->xa, len * 8 - 1);
+ gcry_mpi_clear_bit(this->xa, params->exp_len * 8 - 1);
}
- this->g = gcry_mpi_set_ui(NULL, entry->g);
this->ya = gcry_mpi_new(this->p_len * 8);
this->yb = NULL;
this->zz = NULL;
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c b/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
index d12fe11d5..39609c16c 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
@@ -137,7 +137,7 @@ gcrypt_hasher_t *gcrypt_hasher_create(hash_algorithm_t algo)
err = gcry_md_open(&this->hd, gcrypt_alg, 0);
if (err)
{
- DBG1("grcy_md_open(%N) failed: %s",
+ DBG1(DBG_LIB, "grcy_md_open(%N) failed: %s",
hash_algorithm_names, algo, gpg_strerror(err));
free(this);
return NULL;
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index 8c9ea893b..039036b2c 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -118,7 +118,7 @@ static void destroy(private_gcrypt_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *gcrypt_plugin_create()
{
private_gcrypt_plugin_t *this;
@@ -126,7 +126,7 @@ plugin_t *plugin_create()
if (!gcry_check_version(GCRYPT_VERSION))
{
- DBG1("libgcrypt version mismatch");
+ DBG1(DBG_LIB, "libgcrypt version mismatch");
return NULL;
}
@@ -190,6 +190,10 @@ plugin_t *plugin_create()
/* diffie hellman groups, using modp */
lib->crypto->add_dh(lib->crypto, MODP_2048_BIT,
(dh_constructor_t)gcrypt_dh_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_224,
+ (dh_constructor_t)gcrypt_dh_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_256,
+ (dh_constructor_t)gcrypt_dh_create);
lib->crypto->add_dh(lib->crypto, MODP_1536_BIT,
(dh_constructor_t)gcrypt_dh_create);
lib->crypto->add_dh(lib->crypto, MODP_3072_BIT,
@@ -202,6 +206,8 @@ plugin_t *plugin_create()
(dh_constructor_t)gcrypt_dh_create);
lib->crypto->add_dh(lib->crypto, MODP_1024_BIT,
(dh_constructor_t)gcrypt_dh_create);
+ lib->crypto->add_dh(lib->crypto, MODP_1024_160,
+ (dh_constructor_t)gcrypt_dh_create);
lib->crypto->add_dh(lib->crypto, MODP_768_BIT,
(dh_constructor_t)gcrypt_dh_create);
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.h b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.h
index f2247ed5c..05e5e7014 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.h
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.h
@@ -39,9 +39,4 @@ struct gcrypt_plugin_t {
plugin_t plugin;
};
-/**
- * Create a gcrypt_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** GCRYPT_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
index cd156961e..2cb13c5f3 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
@@ -130,14 +130,15 @@ static bool sign_raw(private_gcrypt_rsa_private_key_t *this,
chunk_free(&em);
if (err)
{
- DBG1("building signature S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building signature S-expression failed: %s",
+ gpg_strerror(err));
return FALSE;
}
err = gcry_pk_sign(&out, in, this->key);
gcry_sexp_release(in);
if (err)
{
- DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err));
return FALSE;
}
*signature = gcrypt_rsa_find_token(out, "s", this->key);
@@ -176,14 +177,14 @@ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
chunk_free(&hash);
if (err)
{
- DBG1("building signature S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building signature S-expression failed: %s", gpg_strerror(err));
return FALSE;
}
err = gcry_pk_sign(&out, in, this->key);
gcry_sexp_release(in);
if (err)
{
- DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err));
return FALSE;
}
*signature = gcrypt_rsa_find_token(out, "s", this->key);
@@ -222,7 +223,7 @@ static bool sign(private_gcrypt_rsa_private_key_t *this, signature_scheme_t sche
case SIGN_RSA_EMSA_PKCS1_MD5:
return sign_pkcs1(this, HASH_MD5, "md5", data, sig);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -243,14 +244,15 @@ static bool decrypt(private_gcrypt_rsa_private_key_t *this,
encrypted.len, encrypted.ptr);
if (err)
{
- DBG1("building decryption S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building decryption S-expression failed: %s",
+ gpg_strerror(err));
return FALSE;
}
err = gcry_pk_decrypt(&out, in, this->key);
gcry_sexp_release(in);
if (err)
{
- DBG1("decrypting pkcs1 data failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "decrypting pkcs1 data failed: %s", gpg_strerror(err));
return FALSE;
}
padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
@@ -269,7 +271,7 @@ static bool decrypt(private_gcrypt_rsa_private_key_t *this,
gcry_sexp_release(out);
if (!pos)
{
- DBG1("decrypted data has invalid pkcs1 padding");
+ DBG1(DBG_LIB, "decrypted data has invalid pkcs1 padding");
return FALSE;
}
return TRUE;
@@ -329,7 +331,7 @@ static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
chunk_clear(&cp);
chunk_clear(&cq);
chunk_clear(&cd);
- DBG1("scanning mpi for export failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "scanning mpi for export failed: %s", gpg_strerror(err));
return FALSE;
}
@@ -340,7 +342,7 @@ static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
gcry_mpi_sub_ui(q, q, 1);
exp2 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
- gcry_mpi_mod(exp1, d, q);
+ gcry_mpi_mod(exp2, d, q);
gcry_mpi_release(q);
err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp1.ptr, &cexp1.len, exp1)
@@ -352,7 +354,7 @@ static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
if (err)
{
- DBG1("printing mpi for export failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "printing mpi for export failed: %s", gpg_strerror(err));
chunk_clear(&cp);
chunk_clear(&cq);
chunk_clear(&cd);
@@ -488,7 +490,7 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type,
err = gcry_sexp_build(&param, NULL, "(genkey(rsa(nbits %d)))", key_size);
if (err)
{
- DBG1("building S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building S-expression failed: %s", gpg_strerror(err));
return NULL;
}
this = gcrypt_rsa_private_key_create_empty();
@@ -497,7 +499,7 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type,
if (err)
{
free(this);
- DBG1("generating RSA key failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "generating RSA key failed: %s", gpg_strerror(err));
return NULL;
}
return &this->public;
@@ -557,14 +559,14 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type,
p.len, p.ptr, q.len, q.ptr, u.len, u.ptr);
if (err)
{
- DBG1("loading private key failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "loading private key failed: %s", gpg_strerror(err));
free(this);
return NULL;
}
err = gcry_pk_testkey(this->key);
if (err)
{
- DBG1("private key sanity check failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "private key sanity check failed: %s", gpg_strerror(err));
destroy(this);
return NULL;
}
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
index e083fac94..5fd15d9a3 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
@@ -83,14 +83,16 @@ static bool verify_raw(private_gcrypt_rsa_public_key_t *this,
chunk_free(&em);
if (err)
{
- DBG1("building data S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building data S-expression failed: %s",
+ gpg_strerror(err));
return FALSE;
}
err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
signature.len, signature.ptr);
if (err)
{
- DBG1("building signature S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building signature S-expression failed: %s",
+ gpg_strerror(err));
gcry_sexp_release(in);
return FALSE;
}
@@ -99,7 +101,8 @@ static bool verify_raw(private_gcrypt_rsa_public_key_t *this,
gcry_sexp_release(sig);
if (err)
{
- DBG1("RSA signature verification failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "RSA signature verification failed: %s",
+ gpg_strerror(err));
return FALSE;
}
return TRUE;
@@ -130,7 +133,8 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
chunk_free(&hash);
if (err)
{
- DBG1("building data S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building data S-expression failed: %s",
+ gpg_strerror(err));
return FALSE;
}
@@ -138,7 +142,8 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
signature.len, signature.ptr);
if (err)
{
- DBG1("building signature S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building signature S-expression failed: %s",
+ gpg_strerror(err));
gcry_sexp_release(in);
return FALSE;
}
@@ -147,7 +152,8 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
gcry_sexp_release(sig);
if (err)
{
- DBG1("RSA signature verification failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "RSA signature verification failed: %s",
+ gpg_strerror(err));
return FALSE;
}
return TRUE;
@@ -184,7 +190,7 @@ static bool verify(private_gcrypt_rsa_public_key_t *this,
case SIGN_RSA_EMSA_PKCS1_SHA512:
return verify_pkcs1(this, HASH_SHA512, "sha512", data, signature);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -205,14 +211,16 @@ static bool encrypt_(private_gcrypt_rsa_public_key_t *this, chunk_t plain,
plain.len, plain.ptr);
if (err)
{
- DBG1("building encryption S-expression failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "building encryption S-expression failed: %s",
+ gpg_strerror(err));
return FALSE;
}
err = gcry_pk_encrypt(&out, in, this->key);
gcry_sexp_release(in);
if (err)
{
- DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s",
+ gpg_strerror(err));
return FALSE;
}
*encrypted = gcrypt_rsa_find_token(out, "a", this->key);
@@ -343,7 +351,7 @@ gcrypt_rsa_public_key_t *gcrypt_rsa_public_key_load(key_type_t type,
n.len, n.ptr, e.len, e.ptr);
if (err)
{
- DBG1("loading public key failed: %s", gpg_strerror(err));
+ DBG1(DBG_LIB, "loading public key failed: %s", gpg_strerror(err));
free(this);
return NULL;
}
diff --git a/src/libstrongswan/plugins/gmp/Makefile.am b/src/libstrongswan/plugins/gmp/Makefile.am
index 1ab358328..cc8ad34db 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.am
+++ b/src/libstrongswan/plugins/gmp/Makefile.am
@@ -3,13 +3,17 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-gmp.la
+else
plugin_LTLIBRARIES = libstrongswan-gmp.la
+endif
-libstrongswan_gmp_la_SOURCES = gmp_plugin.h gmp_plugin.c \
- gmp_diffie_hellman.c gmp_diffie_hellman.h \
- gmp_rsa_private_key.c gmp_rsa_private_key.h \
- gmp_rsa_public_key.c gmp_rsa_public_key.h
+libstrongswan_gmp_la_SOURCES = \
+ gmp_plugin.h gmp_plugin.c \
+ gmp_diffie_hellman.c gmp_diffie_hellman.h \
+ gmp_rsa_private_key.c gmp_rsa_private_key.h \
+ gmp_rsa_public_key.c gmp_rsa_public_key.h
libstrongswan_gmp_la_LDFLAGS = -module -avoid-version
-libstrongswan_gmp_la_LIBADD = -lgmp
-
+libstrongswan_gmp_la_LIBADD = -lgmp
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 3077ea7e8..5c1a1fcd9 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_gmp_la_DEPENDENCIES =
am_libstrongswan_gmp_la_OBJECTS = gmp_plugin.lo gmp_diffie_hellman.lo \
gmp_rsa_private_key.lo gmp_rsa_public_key.lo
@@ -80,6 +80,8 @@ libstrongswan_gmp_la_OBJECTS = $(am_libstrongswan_gmp_la_OBJECTS)
libstrongswan_gmp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_gmp_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_gmp_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_gmp_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,11 +257,13 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-gmp.la
-libstrongswan_gmp_la_SOURCES = gmp_plugin.h gmp_plugin.c \
- gmp_diffie_hellman.c gmp_diffie_hellman.h \
- gmp_rsa_private_key.c gmp_rsa_private_key.h \
- gmp_rsa_public_key.c gmp_rsa_public_key.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-gmp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-gmp.la
+libstrongswan_gmp_la_SOURCES = \
+ gmp_plugin.h gmp_plugin.c \
+ gmp_diffie_hellman.c gmp_diffie_hellman.h \
+ gmp_rsa_private_key.c gmp_rsa_private_key.h \
+ gmp_rsa_public_key.c gmp_rsa_public_key.h
libstrongswan_gmp_la_LDFLAGS = -module -avoid-version
libstrongswan_gmp_la_LIBADD = -lgmp
@@ -296,6 +301,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -328,7 +342,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-gmp.la: $(libstrongswan_gmp_la_OBJECTS) $(libstrongswan_gmp_la_DEPENDENCIES)
- $(libstrongswan_gmp_la_LINK) -rpath $(plugindir) $(libstrongswan_gmp_la_OBJECTS) $(libstrongswan_gmp_la_LIBADD) $(LIBS)
+ $(libstrongswan_gmp_la_LINK) $(am_libstrongswan_gmp_la_rpath) $(libstrongswan_gmp_la_OBJECTS) $(libstrongswan_gmp_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -484,8 +498,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -556,18 +570,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index ea7e6fdd2..4ee449890 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 1999, 2000, 2001 Henry Spencer.
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -22,309 +23,10 @@
#include <debug.h>
-
-/**
- * Modulus of Group 1 (MODP_768_BIT).
- */
-static u_int8_t group1_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 2 (MODP_1024_BIT).
- */
-static u_int8_t group2_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 5 (MODP_1536_BIT).
- */
-static u_int8_t group5_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-/**
- * Modulus of Group 14 (MODP_2048_BIT).
- */
-static u_int8_t group14_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 15 (MODP_3072_BIT).
- */
-static u_int8_t group15_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 16 (MODP_4096_BIT).
- */
-static u_int8_t group16_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 17 (MODP_6144_BIT).
- */
-static u_int8_t group17_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
- 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
- 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
- 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
- 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
- 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
- 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
- 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
- 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
- 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
- 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
- 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
- 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
- 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
- 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
- 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
- 0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-/**
- * Modulus of Group 18 (MODP_8192_BIT).
- */
-static u_int8_t group18_modulus[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
- 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
- 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
- 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
- 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
- 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
- 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
- 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
- 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
- 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
- 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
- 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
- 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
- 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
- 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
- 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
- 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
- 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
- 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
- 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
- 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
- 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
- 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
- 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
- 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
- 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
- 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
- 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
- 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
- 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
- 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
- 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
- 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
- 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
- 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
- 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
- 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
- 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
- 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
- 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
- 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
- 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
- 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
- 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
- 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
- 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
- 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
- 0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
- 0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA,
- 0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,
- 0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
- 0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D,
- 0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,
- 0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
- 0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8,
- 0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,
- 0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
- 0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D,
- 0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,
- 0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
- 0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B,
- 0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,
- 0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
- 0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-};
-
-typedef struct modulus_entry_t modulus_entry_t;
-
-/**
- * Entry of the modulus list.
- */
-struct modulus_entry_t {
- /**
- * Group number as it is defined in file transform_substructure.h.
- */
- diffie_hellman_group_t group;
-
- /**
- * Pointer to first byte of modulus (network order).
- */
- u_int8_t *modulus;
-
- /*
- * Length of modulus in bytes.
- */
- size_t modulus_len;
-
- /*
- * Optimum length of exponent in bytes.
- */
- size_t opt_exponent_len;
-
- /*
- * Generator value.
- */
- u_int16_t generator;
-};
-
-/**
- * All supported modulus values - optimum exponent size according to RFC 3526.
- */
-static modulus_entry_t modulus_entries[] = {
- {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 32, 2},
- {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 32, 2},
- {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 32, 2},
- {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 48, 2},
- {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 48, 2},
- {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 64, 2},
- {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 64, 2},
- {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 64, 2},
-};
+#ifdef HAVE_MPZ_POWM_SEC
+# undef mpz_powm
+# define mpz_powm mpz_powm_sec
+#endif
typedef struct private_gmp_diffie_hellman_t private_gmp_diffie_hellman_t;
@@ -378,11 +80,6 @@ struct private_gmp_diffie_hellman_t {
size_t p_len;
/**
- * Optimal exponent length.
- */
- size_t opt_exponent_len;
-
- /**
* True if shared secret is computed and stored in my_public_value.
*/
bool computed;
@@ -409,10 +106,20 @@ static void set_other_public_value(private_gmp_diffie_hellman_t *this, chunk_t v
#ifdef EXTENDED_DH_TEST
/* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */
mpz_t q, one;
+ diffie_hellman_params_t *params;
mpz_init(q);
mpz_init(one);
- mpz_fdiv_q_2exp(q, p_min_1, 1);
+
+ params = diffie_hellman_get_params(this->group);
+ if (!params->subgroup.len)
+ {
+ mpz_fdiv_q_2exp(q, p_min_1, 1);
+ }
+ else
+ {
+ mpz_import(q, params->subgroup.len, 1, 1, 1, 0, params->subgroup.ptr);
+ }
mpz_powm(one, this->yb, q, this->p);
mpz_clear(q);
if (mpz_cmp_ui(one, 1) == 0)
@@ -422,7 +129,8 @@ static void set_other_public_value(private_gmp_diffie_hellman_t *this, chunk_t v
}
else
{
- DBG1("public DH value verification failed: y ^ q mod p != 1");
+ DBG1(DBG_LIB, "public DH value verification failed:"
+ " y ^ q mod p != 1");
}
mpz_clear(one);
#else
@@ -432,7 +140,8 @@ static void set_other_public_value(private_gmp_diffie_hellman_t *this, chunk_t v
}
else
{
- DBG1("public DH value verification failed: y < 2 || y > p - 1 ");
+ DBG1(DBG_LIB, "public DH value verification failed:"
+ " y < 2 || y > p - 1 ");
}
mpz_clear(p_min_1);
}
@@ -477,32 +186,6 @@ static diffie_hellman_group_t get_dh_group(private_gmp_diffie_hellman_t *this)
}
/**
- * Lookup the modulus in modulo table
- */
-static status_t set_modulus(private_gmp_diffie_hellman_t *this)
-{
- int i;
- status_t status = NOT_FOUND;
-
- for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
- {
- if (modulus_entries[i].group == this->group)
- {
- chunk_t chunk;
- chunk.ptr = modulus_entries[i].modulus;
- chunk.len = modulus_entries[i].modulus_len;
- mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr);
- this->p_len = chunk.len;
- this->opt_exponent_len = modulus_entries[i].opt_exponent_len;
- mpz_set_ui(this->g, modulus_entries[i].generator);
- status = SUCCESS;
- break;
- }
- }
- return status;
-}
-
-/**
* Implementation of gmp_diffie_hellman_t.destroy.
*/
static void destroy(private_gmp_diffie_hellman_t *this)
@@ -521,11 +204,18 @@ static void destroy(private_gmp_diffie_hellman_t *this)
*/
gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
{
- private_gmp_diffie_hellman_t *this = malloc_thing(private_gmp_diffie_hellman_t);
+ private_gmp_diffie_hellman_t *this;
+ diffie_hellman_params_t *params;
rng_t *rng;
chunk_t random;
- bool ansi_x9_42;
- size_t exponent_len;
+
+ params = diffie_hellman_get_params(group);
+ if (!params)
+ {
+ return NULL;
+ }
+
+ this = malloc_thing(private_gmp_diffie_hellman_t);
/* public functions */
this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
@@ -544,35 +234,31 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
mpz_init(this->g);
this->computed = FALSE;
+ this->p_len = params->prime.len;
+ mpz_import(this->p, params->prime.len, 1, 1, 1, 0, params->prime.ptr);
+ mpz_import(this->g, params->generator.len, 1, 1, 1, 0, params->generator.ptr);
- /* find a modulus according to group */
- if (set_modulus(this) != SUCCESS)
- {
- destroy(this);
- return NULL;
- }
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (!rng)
{
- DBG1("no RNG found for quality %N", rng_quality_names, RNG_STRONG);
+ DBG1(DBG_LIB, "no RNG found for quality %N", rng_quality_names,
+ RNG_STRONG);
destroy(this);
return NULL;
}
- ansi_x9_42 = lib->settings->get_int(lib->settings,
- "libstrongswan.dh_exponent_ansi_x9_42", TRUE);
- exponent_len = (ansi_x9_42) ? this->p_len : this->opt_exponent_len;
- rng->allocate_bytes(rng, exponent_len, &random);
+ rng->allocate_bytes(rng, params->exp_len, &random);
rng->destroy(rng);
- if (ansi_x9_42)
+ if (params->exp_len == this->p_len)
{
/* achieve bitsof(p)-1 by setting MSB to 0 */
*random.ptr &= 0x7F;
}
mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random);
- DBG2("size of DH secret exponent: %u bits", mpz_sizeinbase(this->xa, 2));
+ DBG2(DBG_LIB, "size of DH secret exponent: %u bits",
+ mpz_sizeinbase(this->xa, 2));
mpz_powm(this->ya, this->g, this->xa, this->p);
diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c
index b70ff881c..fbce9732f 100644
--- a/src/libstrongswan/plugins/gmp/gmp_plugin.c
+++ b/src/libstrongswan/plugins/gmp/gmp_plugin.c
@@ -52,7 +52,7 @@ static void destroy(private_gmp_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *gmp_plugin_create()
{
private_gmp_plugin_t *this = malloc_thing(private_gmp_plugin_t);
@@ -60,6 +60,10 @@ plugin_t *plugin_create()
lib->crypto->add_dh(lib->crypto, MODP_2048_BIT,
(dh_constructor_t)gmp_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_224,
+ (dh_constructor_t)gmp_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_256,
+ (dh_constructor_t)gmp_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1536_BIT,
(dh_constructor_t)gmp_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_3072_BIT,
@@ -72,6 +76,8 @@ plugin_t *plugin_create()
(dh_constructor_t)gmp_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1024_BIT,
(dh_constructor_t)gmp_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_1024_160,
+ (dh_constructor_t)gmp_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_768_BIT,
(dh_constructor_t)gmp_diffie_hellman_create);
diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.h b/src/libstrongswan/plugins/gmp/gmp_plugin.h
index 77d53965d..e4a87c8e2 100644
--- a/src/libstrongswan/plugins/gmp/gmp_plugin.h
+++ b/src/libstrongswan/plugins/gmp/gmp_plugin.h
@@ -39,9 +39,4 @@ struct gmp_plugin_t {
plugin_t plugin;
};
-/**
- * Create a gmp_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** GMP_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
index 1829bd459..f70b0b545 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
@@ -27,6 +27,11 @@
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
+#ifdef HAVE_MPZ_POWM_SEC
+# undef mpz_powm
+# define mpz_powm mpz_powm_sec
+#endif
+
/**
* Public exponent to use for key generation.
*/
@@ -136,7 +141,8 @@ static status_t compute_prime(private_gmp_rsa_private_key_t *this,
rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
if (!rng)
{
- DBG1("no RNG of quality %N found", rng_quality_names, RNG_TRUE);
+ DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names,
+ RNG_TRUE);
return FAILED;
}
@@ -144,8 +150,8 @@ static status_t compute_prime(private_gmp_rsa_private_key_t *this,
do
{
rng->allocate_bytes(rng, prime_size, &random_bytes);
- /* make sure most significant bit is set */
- random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
+ /* make sure the two most significant bits are set */
+ random_bytes.ptr[0] = random_bytes.ptr[0] | 0xC0;
mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
mpz_nextprime (*prime, *prime);
@@ -243,7 +249,8 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
if (data.len > this->k - 3)
{
free(digestInfo.ptr);
- DBG1("unable to sign %d bytes using a %dbit key", data.len, this->k * 8);
+ DBG1(DBG_LIB, "unable to sign %d bytes using a %dbit key", data.len,
+ this->k * 8);
return FALSE;
}
@@ -304,7 +311,7 @@ static bool sign(private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
case SIGN_RSA_EMSA_PKCS1_MD5:
return build_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -327,7 +334,7 @@ static bool decrypt(private_gmp_rsa_private_key_t *this, chunk_t crypto,
/* check for hex pattern 00 02 in decrypted message */
if ((*stripped.ptr++ != 0x00) || (*(stripped.ptr++) != 0x02))
{
- DBG1("incorrect padding - probably wrong rsa key");
+ DBG1(DBG_LIB, "incorrect padding - probably wrong rsa key");
goto end;
}
stripped.len -= 2;
@@ -337,7 +344,7 @@ static bool decrypt(private_gmp_rsa_private_key_t *this, chunk_t crypto,
if (stripped.len == 0)
{
- DBG1("no plaintext data");
+ DBG1(DBG_LIB, "no plaintext data");
goto end;
}
@@ -494,14 +501,14 @@ static status_t check(private_gmp_rsa_private_key_t *this)
*/
if (this->k < 512 / BITS_PER_BYTE)
{
- DBG1("key shorter than 512 bits");
+ DBG1(DBG_LIB, "key shorter than 512 bits");
return FAILED;
}
/* we picked a max modulus size to simplify buffer allocation */
if (this->k > 8192 / BITS_PER_BYTE)
{
- DBG1("key larger than 8192 bits");
+ DBG1(DBG_LIB, "key larger than 8192 bits");
return FAILED;
}
@@ -575,7 +582,7 @@ static status_t check(private_gmp_rsa_private_key_t *this)
mpz_clear_sensitive(q1);
if (status != SUCCESS)
{
- DBG1("key integrity tests failed");
+ DBG1(DBG_LIB, "key integrity tests failed");
}
return status;
}
@@ -664,7 +671,7 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
mpz_mul(n, p, q); /* n = p*q */
mpz_init_set_ui(e, PUBLIC_EXPONENT); /* assign public exponent */
- mpz_init_set(m, p); /* m = p */
+ mpz_init_set(m, p); /* m = p */
mpz_sub_ui(m, m, 1); /* m = m -1 */
mpz_init_set(q1, q); /* q1 = q */
mpz_sub_ui(q1, q1, 1); /* q1 = q1 -1 */
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index 5fea69131..98dbb1922 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -28,6 +28,11 @@
#include <asn1/asn1_parser.h>
#include <crypto/hashers/hasher.h>
+#ifdef HAVE_MPZ_POWM_SEC
+# undef mpz_powm
+# define mpz_powm mpz_powm_sec
+#endif
+
typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
/**
@@ -178,8 +183,8 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
{ /* IKEv1 signatures without digestInfo */
if (em.len != data.len)
{
- DBG1("hash size in signature is %u bytes instead of %u bytes",
- em.len, data.len);
+ DBG1(DBG_LIB, "hash size in signature is %u bytes instead of"
+ " %u bytes", em.len, data.len);
goto end;
}
success = memeq(em.ptr, data.ptr, data.len);
@@ -191,7 +196,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
int objectID;
hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
- DBG2("signature verification:");
+ DBG2(DBG_LIB, "signature verification:");
parser = asn1_parser_create(digestInfoObjects, em);
while (parser->iterate(parser, &objectID, &object))
@@ -202,7 +207,8 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
{
if (em.len > object.len)
{
- DBG1("digestInfo field in signature is followed by %u surplus bytes",
+ DBG1(DBG_LIB, "digestInfo field in signature is"
+ " followed by %u surplus bytes",
em.len - object.len);
goto end_parser;
}
@@ -216,8 +222,8 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
hash_algorithm = hasher_algorithm_from_oid(hash_oid);
if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm)
{
- DBG1("expected hash algorithm %N, but found %N (OID: %#B)",
- hash_algorithm_names, algorithm,
+ DBG1(DBG_LIB, "expected hash algorithm %N, but found"
+ " %N (OID: %#B)", hash_algorithm_names, algorithm,
hash_algorithm_names, hash_algorithm, &object);
goto end_parser;
}
@@ -231,15 +237,16 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
if (hasher == NULL)
{
- DBG1("hash algorithm %N not supported",
+ DBG1(DBG_LIB, "hash algorithm %N not supported",
hash_algorithm_names, hash_algorithm);
goto end_parser;
}
if (object.len != hasher->get_hash_size(hasher))
{
- DBG1("hash size in signature is %u bytes instead of %u "
- "bytes", object.len, hasher->get_hash_size(hasher));
+ DBG1(DBG_LIB, "hash size in signature is %u bytes"
+ " instead of %u bytes", object.len,
+ hasher->get_hash_size(hasher));
hasher->destroy(hasher);
goto end_parser;
}
@@ -297,7 +304,7 @@ static bool verify(private_gmp_rsa_public_key_t *this, signature_scheme_t scheme
case SIGN_RSA_EMSA_PKCS1_SHA512:
return verify_emsa_pkcs1_signature(this, HASH_SHA512, data, signature);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -319,7 +326,7 @@ static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t plain,
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (rng == NULL)
{
- DBG1("no random generator available");
+ DBG1(DBG_LIB, "no random generator available");
return FALSE;
}
@@ -327,13 +334,14 @@ static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t plain,
padding = this->k - plain.len - 3;
if (padding < MIN_PS_PADDING)
{
- DBG1("pseudo-random padding must be at least %d octets", MIN_PS_PADDING);
+ DBG1(DBG_LIB, "pseudo-random padding must be at least %d octets",
+ MIN_PS_PADDING);
return FALSE;
}
/* padding according to PKCS#1 7.2.1 (RSAES-PKCS1-v1.5-ENCRYPT) */
- DBG2("padding %u bytes of data to the rsa modulus size of %u bytes",
- plain.len, this->k);
+ DBG2(DBG_LIB, "padding %u bytes of data to the rsa modulus size of"
+ " %u bytes", plain.len, this->k);
em.len = this->k;
em.ptr = malloc(em.len);
pos = em.ptr;
@@ -359,11 +367,11 @@ static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t plain,
/* now add the data */
memcpy(pos, plain.ptr, plain.len);
- DBG3("padded data before rsa encryption: %B", &em);
+ DBG3(DBG_LIB, "padded data before rsa encryption: %B", &em);
/* rsa encryption using PKCS#1 RSAEP */
*crypto = rsaep(this, em);
- DBG3("rsa encrypted data: %B", crypto);
+ DBG3(DBG_LIB, "rsa encrypted data: %B", crypto);
chunk_clear(&em);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/hmac/Makefile.am b/src/libstrongswan/plugins/hmac/Makefile.am
index 1856cad2d..77aa0ffd1 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.am
+++ b/src/libstrongswan/plugins/hmac/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-hmac.la
+else
plugin_LTLIBRARIES = libstrongswan-hmac.la
+endif
-libstrongswan_hmac_la_SOURCES = hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
+libstrongswan_hmac_la_SOURCES = \
+ hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
hmac_prf.h hmac_prf.c hmac_signer.h hmac_signer.c
-libstrongswan_hmac_la_LDFLAGS = -module -avoid-version
+libstrongswan_hmac_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in
index 7dc8269a4..c965f7392 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.in
+++ b/src/libstrongswan/plugins/hmac/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_hmac_la_LIBADD =
am_libstrongswan_hmac_la_OBJECTS = hmac_plugin.lo hmac.lo hmac_prf.lo \
hmac_signer.lo
@@ -80,6 +80,8 @@ libstrongswan_hmac_la_OBJECTS = $(am_libstrongswan_hmac_la_OBJECTS)
libstrongswan_hmac_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_hmac_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_hmac_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_hmac_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,8 +257,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-hmac.la
-libstrongswan_hmac_la_SOURCES = hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-hmac.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-hmac.la
+libstrongswan_hmac_la_SOURCES = \
+ hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
hmac_prf.h hmac_prf.c hmac_signer.h hmac_signer.c
libstrongswan_hmac_la_LDFLAGS = -module -avoid-version
@@ -293,6 +298,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -325,7 +339,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-hmac.la: $(libstrongswan_hmac_la_OBJECTS) $(libstrongswan_hmac_la_DEPENDENCIES)
- $(libstrongswan_hmac_la_LINK) -rpath $(plugindir) $(libstrongswan_hmac_la_OBJECTS) $(libstrongswan_hmac_la_LIBADD) $(LIBS)
+ $(libstrongswan_hmac_la_LINK) $(am_libstrongswan_hmac_la_rpath) $(libstrongswan_hmac_la_OBJECTS) $(libstrongswan_hmac_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -481,8 +495,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -553,18 +567,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/hmac/hmac_plugin.c b/src/libstrongswan/plugins/hmac/hmac_plugin.c
index 94332ee36..e6b9f7a74 100644
--- a/src/libstrongswan/plugins/hmac/hmac_plugin.c
+++ b/src/libstrongswan/plugins/hmac/hmac_plugin.c
@@ -47,7 +47,7 @@ static void destroy(private_hmac_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *hmac_plugin_create()
{
private_hmac_plugin_t *this = malloc_thing(private_hmac_plugin_t);
diff --git a/src/libstrongswan/plugins/hmac/hmac_plugin.h b/src/libstrongswan/plugins/hmac/hmac_plugin.h
index 5c3afa7d6..03d1d1cf9 100644
--- a/src/libstrongswan/plugins/hmac/hmac_plugin.h
+++ b/src/libstrongswan/plugins/hmac/hmac_plugin.h
@@ -39,9 +39,4 @@ struct hmac_plugin_t {
plugin_t plugin;
};
-/**
- * Create a hmac_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** HMAC_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/ldap/Makefile.am b/src/libstrongswan/plugins/ldap/Makefile.am
index 6ad073d97..2b2f7d31d 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.am
+++ b/src/libstrongswan/plugins/ldap/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ldap.la
+else
plugin_LTLIBRARIES = libstrongswan-ldap.la
+endif
+
+libstrongswan_ldap_la_SOURCES = \
+ ldap_plugin.h ldap_plugin.c ldap_fetcher.h ldap_fetcher.c
-libstrongswan_ldap_la_SOURCES = ldap_plugin.h ldap_plugin.c ldap_fetcher.h ldap_fetcher.c
libstrongswan_ldap_la_LDFLAGS = -module -avoid-version
libstrongswan_ldap_la_LIBADD = -lldap -llber
-
diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in
index d9ebb0147..3b69f082f 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.in
+++ b/src/libstrongswan/plugins/ldap/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_ldap_la_DEPENDENCIES =
am_libstrongswan_ldap_la_OBJECTS = ldap_plugin.lo ldap_fetcher.lo
libstrongswan_ldap_la_OBJECTS = $(am_libstrongswan_ldap_la_OBJECTS)
libstrongswan_ldap_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_ldap_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_ldap_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_ldap_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-ldap.la
-libstrongswan_ldap_la_SOURCES = ldap_plugin.h ldap_plugin.c ldap_fetcher.h ldap_fetcher.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ldap.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ldap.la
+libstrongswan_ldap_la_SOURCES = \
+ ldap_plugin.h ldap_plugin.c ldap_fetcher.h ldap_fetcher.c
+
libstrongswan_ldap_la_LDFLAGS = -module -avoid-version
libstrongswan_ldap_la_LIBADD = -lldap -llber
all: all-am
@@ -291,6 +297,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -323,7 +338,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-ldap.la: $(libstrongswan_ldap_la_OBJECTS) $(libstrongswan_ldap_la_DEPENDENCIES)
- $(libstrongswan_ldap_la_LINK) -rpath $(plugindir) $(libstrongswan_ldap_la_OBJECTS) $(libstrongswan_ldap_la_LIBADD) $(LIBS)
+ $(libstrongswan_ldap_la_LINK) $(am_libstrongswan_ldap_la_rpath) $(libstrongswan_ldap_la_OBJECTS) $(libstrongswan_ldap_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -477,8 +492,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -549,18 +564,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/ldap/ldap_fetcher.c b/src/libstrongswan/plugins/ldap/ldap_fetcher.c
index ce5b7d56b..59e655cd5 100644
--- a/src/libstrongswan/plugins/ldap/ldap_fetcher.c
+++ b/src/libstrongswan/plugins/ldap/ldap_fetcher.c
@@ -73,27 +73,27 @@ static bool parse(LDAP *ldap, LDAPMessage *result, chunk_t *response)
}
else
{
- DBG1("LDAP response contains no values");
+ DBG1(DBG_LIB, "LDAP response contains no values");
}
ldap_value_free_len(values);
}
else
{
- DBG1("getting LDAP values failed: %s",
+ DBG1(DBG_LIB, "getting LDAP values failed: %s",
ldap_err2string(ldap_result2error(ldap, entry, 0)));
}
ldap_memfree(attr);
}
else
{
- DBG1("finding LDAP attributes failed: %s",
+ DBG1(DBG_LIB, "finding LDAP attributes failed: %s",
ldap_err2string(ldap_result2error(ldap, entry, 0)));
}
ber_free(ber, 0);
}
else
{
- DBG1("finding first LDAP entry failed: %s",
+ DBG1(DBG_LIB, "finding first LDAP entry failed: %s",
ldap_err2string(ldap_result2error(ldap, entry, 0)));
}
return success;
@@ -122,7 +122,7 @@ static status_t fetch(private_ldap_fetcher_t *this, char *url,
ldap = ldap_init(lurl->lud_host, lurl->lud_port);
if (ldap == NULL)
{
- DBG1("LDAP initialization failed: %s", strerror(errno));
+ DBG1(DBG_LIB, "LDAP initialization failed: %s", strerror(errno));
ldap_free_urldesc(lurl);
return FAILED;
}
@@ -133,7 +133,7 @@ static status_t fetch(private_ldap_fetcher_t *this, char *url,
ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
- DBG2("sending LDAP request to '%s'...", url);
+ DBG2(DBG_LIB, "sending LDAP request to '%s'...", url);
res = ldap_simple_bind_s(ldap, NULL, NULL);
if (res == LDAP_SUCCESS)
@@ -152,12 +152,13 @@ static status_t fetch(private_ldap_fetcher_t *this, char *url,
}
else
{
- DBG1("LDAP search failed: %s", ldap_err2string(res));
+ DBG1(DBG_LIB, "LDAP search failed: %s", ldap_err2string(res));
}
}
else
{
- DBG1("LDAP bind to '%s' failed: %s", url, ldap_err2string(res));
+ DBG1(DBG_LIB, "LDAP bind to '%s' failed: %s", url,
+ ldap_err2string(res));
}
ldap_unbind_s(ldap);
ldap_free_urldesc(lurl);
diff --git a/src/libstrongswan/plugins/ldap/ldap_plugin.c b/src/libstrongswan/plugins/ldap/ldap_plugin.c
index a31308bbf..372ac9f93 100644
--- a/src/libstrongswan/plugins/ldap/ldap_plugin.c
+++ b/src/libstrongswan/plugins/ldap/ldap_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_ldap_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *ldap_plugin_create()
{
private_ldap_plugin_t *this = malloc_thing(private_ldap_plugin_t);
diff --git a/src/libstrongswan/plugins/ldap/ldap_plugin.h b/src/libstrongswan/plugins/ldap/ldap_plugin.h
index de4ff3422..e4fcebaa3 100644
--- a/src/libstrongswan/plugins/ldap/ldap_plugin.h
+++ b/src/libstrongswan/plugins/ldap/ldap_plugin.h
@@ -39,9 +39,4 @@ struct ldap_plugin_t {
plugin_t plugin;
};
-/**
- * Create a ldap_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** LDAP_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/md4/Makefile.am b/src/libstrongswan/plugins/md4/Makefile.am
index a47da2e8e..904af70c0 100644
--- a/src/libstrongswan/plugins/md4/Makefile.am
+++ b/src/libstrongswan/plugins/md4/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-md4.la
+else
plugin_LTLIBRARIES = libstrongswan-md4.la
+endif
-libstrongswan_md4_la_SOURCES = md4_plugin.h md4_plugin.c md4_hasher.c md4_hasher.h
-libstrongswan_md4_la_LDFLAGS = -module -avoid-version
+libstrongswan_md4_la_SOURCES = \
+ md4_plugin.h md4_plugin.c md4_hasher.c md4_hasher.h
+libstrongswan_md4_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in
index 6014ddcf8..cb3307bbc 100644
--- a/src/libstrongswan/plugins/md4/Makefile.in
+++ b/src/libstrongswan/plugins/md4/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_md4_la_LIBADD =
am_libstrongswan_md4_la_OBJECTS = md4_plugin.lo md4_hasher.lo
libstrongswan_md4_la_OBJECTS = $(am_libstrongswan_md4_la_OBJECTS)
libstrongswan_md4_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_md4_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_md4_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_md4_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-md4.la
-libstrongswan_md4_la_SOURCES = md4_plugin.h md4_plugin.c md4_hasher.c md4_hasher.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-md4.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-md4.la
+libstrongswan_md4_la_SOURCES = \
+ md4_plugin.h md4_plugin.c md4_hasher.c md4_hasher.h
+
libstrongswan_md4_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -290,6 +296,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -322,7 +337,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-md4.la: $(libstrongswan_md4_la_OBJECTS) $(libstrongswan_md4_la_DEPENDENCIES)
- $(libstrongswan_md4_la_LINK) -rpath $(plugindir) $(libstrongswan_md4_la_OBJECTS) $(libstrongswan_md4_la_LIBADD) $(LIBS)
+ $(libstrongswan_md4_la_LINK) $(am_libstrongswan_md4_la_rpath) $(libstrongswan_md4_la_OBJECTS) $(libstrongswan_md4_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -476,8 +491,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -548,18 +563,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/md4/md4_plugin.c b/src/libstrongswan/plugins/md4/md4_plugin.c
index ba4041d2d..38ae0d4bc 100644
--- a/src/libstrongswan/plugins/md4/md4_plugin.c
+++ b/src/libstrongswan/plugins/md4/md4_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_md4_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *md4_plugin_create()
{
private_md4_plugin_t *this = malloc_thing(private_md4_plugin_t);
diff --git a/src/libstrongswan/plugins/md4/md4_plugin.h b/src/libstrongswan/plugins/md4/md4_plugin.h
index b13002d7b..9fde665e6 100644
--- a/src/libstrongswan/plugins/md4/md4_plugin.h
+++ b/src/libstrongswan/plugins/md4/md4_plugin.h
@@ -39,9 +39,4 @@ struct md4_plugin_t {
plugin_t plugin;
};
-/**
- * Create a md4_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** MD4_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/md5/Makefile.am b/src/libstrongswan/plugins/md5/Makefile.am
index ce0611c13..b2eb2abd2 100644
--- a/src/libstrongswan/plugins/md5/Makefile.am
+++ b/src/libstrongswan/plugins/md5/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-md5.la
+else
plugin_LTLIBRARIES = libstrongswan-md5.la
+endif
-libstrongswan_md5_la_SOURCES = md5_plugin.h md5_plugin.c md5_hasher.c md5_hasher.h
-libstrongswan_md5_la_LDFLAGS = -module -avoid-version
+libstrongswan_md5_la_SOURCES = \
+ md5_plugin.h md5_plugin.c md5_hasher.c md5_hasher.h
+libstrongswan_md5_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in
index fcb921316..8948ddcc5 100644
--- a/src/libstrongswan/plugins/md5/Makefile.in
+++ b/src/libstrongswan/plugins/md5/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_md5_la_LIBADD =
am_libstrongswan_md5_la_OBJECTS = md5_plugin.lo md5_hasher.lo
libstrongswan_md5_la_OBJECTS = $(am_libstrongswan_md5_la_OBJECTS)
libstrongswan_md5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_md5_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_md5_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_md5_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-md5.la
-libstrongswan_md5_la_SOURCES = md5_plugin.h md5_plugin.c md5_hasher.c md5_hasher.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-md5.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-md5.la
+libstrongswan_md5_la_SOURCES = \
+ md5_plugin.h md5_plugin.c md5_hasher.c md5_hasher.h
+
libstrongswan_md5_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -290,6 +296,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -322,7 +337,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-md5.la: $(libstrongswan_md5_la_OBJECTS) $(libstrongswan_md5_la_DEPENDENCIES)
- $(libstrongswan_md5_la_LINK) -rpath $(plugindir) $(libstrongswan_md5_la_OBJECTS) $(libstrongswan_md5_la_LIBADD) $(LIBS)
+ $(libstrongswan_md5_la_LINK) $(am_libstrongswan_md5_la_rpath) $(libstrongswan_md5_la_OBJECTS) $(libstrongswan_md5_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -476,8 +491,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -548,18 +563,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/md5/md5_plugin.c b/src/libstrongswan/plugins/md5/md5_plugin.c
index 7592c20df..cfbf6acea 100644
--- a/src/libstrongswan/plugins/md5/md5_plugin.c
+++ b/src/libstrongswan/plugins/md5/md5_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_md5_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *md5_plugin_create()
{
private_md5_plugin_t *this = malloc_thing(private_md5_plugin_t);
diff --git a/src/libstrongswan/plugins/md5/md5_plugin.h b/src/libstrongswan/plugins/md5/md5_plugin.h
index 057689ad3..c4ca619dc 100644
--- a/src/libstrongswan/plugins/md5/md5_plugin.h
+++ b/src/libstrongswan/plugins/md5/md5_plugin.h
@@ -39,9 +39,4 @@ struct md5_plugin_t {
plugin_t plugin;
};
-/**
- * Create a md5_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** MD5_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/mysql/Makefile.am b/src/libstrongswan/plugins/mysql/Makefile.am
index c64481fd5..801a7a7be 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.am
+++ b/src/libstrongswan/plugins/mysql/Makefile.am
@@ -3,10 +3,16 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic $(MYSQLCFLAG)
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-mysql.la
+else
plugin_LTLIBRARIES = libstrongswan-mysql.la
+endif
-libstrongswan_mysql_la_SOURCES = mysql_plugin.h mysql_plugin.c \
+libstrongswan_mysql_la_SOURCES = \
+ mysql_plugin.h mysql_plugin.c \
mysql_database.h mysql_database.c
+
libstrongswan_mysql_la_LDFLAGS = -module -avoid-version
-libstrongswan_mysql_la_LIBADD = $(MYSQLLIB)
+libstrongswan_mysql_la_LIBADD = $(MYSQLLIB)
diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in
index dc56940d2..1a97c620e 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.in
+++ b/src/libstrongswan/plugins/mysql/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
am__DEPENDENCIES_1 =
libstrongswan_mysql_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_libstrongswan_mysql_la_OBJECTS = mysql_plugin.lo mysql_database.lo
@@ -80,6 +80,9 @@ libstrongswan_mysql_la_OBJECTS = $(am_libstrongswan_mysql_la_OBJECTS)
libstrongswan_mysql_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_mysql_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_mysql_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_mysql_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,8 +258,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic $(MYSQLCFLAG)
-plugin_LTLIBRARIES = libstrongswan-mysql.la
-libstrongswan_mysql_la_SOURCES = mysql_plugin.h mysql_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-mysql.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-mysql.la
+libstrongswan_mysql_la_SOURCES = \
+ mysql_plugin.h mysql_plugin.c \
mysql_database.h mysql_database.c
libstrongswan_mysql_la_LDFLAGS = -module -avoid-version
@@ -294,6 +300,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -326,7 +341,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-mysql.la: $(libstrongswan_mysql_la_OBJECTS) $(libstrongswan_mysql_la_DEPENDENCIES)
- $(libstrongswan_mysql_la_LINK) -rpath $(plugindir) $(libstrongswan_mysql_la_OBJECTS) $(libstrongswan_mysql_la_LIBADD) $(LIBS)
+ $(libstrongswan_mysql_la_LINK) $(am_libstrongswan_mysql_la_rpath) $(libstrongswan_mysql_la_OBJECTS) $(libstrongswan_mysql_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -480,8 +495,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -552,18 +567,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c
index 2338428f2..8005b9149 100644
--- a/src/libstrongswan/plugins/mysql/mysql_database.c
+++ b/src/libstrongswan/plugins/mysql/mysql_database.c
@@ -203,7 +203,7 @@ static conn_t *conn_get(private_mysql_database_t *this)
this->password, this->database, this->port,
NULL, 0))
{
- DBG1("connecting to mysql://%s:***@%s:%d/%s failed: %s",
+ DBG1(DBG_LIB, "connecting to mysql://%s:***@%s:%d/%s failed: %s",
this->username, this->host, this->port, this->database,
mysql_error(found->mysql));
conn_destroy(found);
@@ -213,7 +213,7 @@ static conn_t *conn_get(private_mysql_database_t *this)
{
this->mutex->lock(this->mutex);
this->pool->insert_last(this->pool, found);
- DBG2("increased MySQL connection pool size to %d",
+ DBG2(DBG_LIB, "increased MySQL connection pool size to %d",
this->pool->get_count(this->pool));
this->mutex->unlock(this->mutex);
}
@@ -232,12 +232,14 @@ static MYSQL_STMT* run(MYSQL *mysql, char *sql, va_list *args)
stmt = mysql_stmt_init(mysql);
if (stmt == NULL)
{
- DBG1("creating MySQL statement failed: %s", mysql_error(mysql));
+ DBG1(DBG_LIB, "creating MySQL statement failed: %s",
+ mysql_error(mysql));
return NULL;
}
if (mysql_stmt_prepare(stmt, sql, strlen(sql)))
{
- DBG1("preparing MySQL statement failed: %s", mysql_stmt_error(stmt));
+ DBG1(DBG_LIB, "preparing MySQL statement failed: %s",
+ mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return NULL;
}
@@ -303,21 +305,23 @@ static MYSQL_STMT* run(MYSQL *mysql, char *sql, va_list *args)
break;
}
default:
- DBG1("invalid data type supplied");
+ DBG1(DBG_LIB, "invalid data type supplied");
mysql_stmt_close(stmt);
return NULL;
}
}
if (mysql_stmt_bind_param(stmt, bind))
{
- DBG1("binding MySQL param failed: %s", mysql_stmt_error(stmt));
+ DBG1(DBG_LIB, "binding MySQL param failed: %s",
+ mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return NULL;
}
}
if (mysql_stmt_execute(stmt))
{
- DBG1("executing MySQL statement failed: %s", mysql_stmt_error(stmt));
+ DBG1(DBG_LIB, "executing MySQL statement failed: %s",
+ mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return NULL;
}
@@ -413,7 +417,8 @@ static bool mysql_enumerator_enumerate(mysql_enumerator_t *this, ...)
case MYSQL_NO_DATA:
return FALSE;
default:
- DBG1("fetching MySQL row failed: %s", mysql_stmt_error(this->stmt));
+ DBG1(DBG_LIB, "fetching MySQL row failed: %s",
+ mysql_stmt_error(this->stmt));
return FALSE;
}
@@ -536,7 +541,7 @@ static enumerator_t* query(private_mysql_database_t *this, char *sql, ...)
break;
}
default:
- DBG1("invalid result data type supplied");
+ DBG1(DBG_LIB, "invalid result data type supplied");
mysql_enumerator_destroy(enumerator);
va_end(args);
return NULL;
@@ -544,7 +549,8 @@ static enumerator_t* query(private_mysql_database_t *this, char *sql, ...)
}
if (mysql_stmt_bind_result(stmt, enumerator->bind))
{
- DBG1("binding MySQL result failed: %s", mysql_stmt_error(stmt));
+ DBG1(DBG_LIB, "binding MySQL result failed: %s",
+ mysql_stmt_error(stmt));
mysql_enumerator_destroy(enumerator);
enumerator = NULL;
}
@@ -653,7 +659,7 @@ static bool parse_uri(private_mysql_database_t *this, char *uri)
}
}
}
- DBG1("parsing MySQL database uri '%s' failed", uri);
+ DBG1(DBG_LIB, "parsing MySQL database uri '%s' failed", uri);
return FALSE;
}
diff --git a/src/libstrongswan/plugins/mysql/mysql_plugin.c b/src/libstrongswan/plugins/mysql/mysql_plugin.c
index 0e64bbc3d..a13aa8091 100644
--- a/src/libstrongswan/plugins/mysql/mysql_plugin.c
+++ b/src/libstrongswan/plugins/mysql/mysql_plugin.c
@@ -46,13 +46,13 @@ static void destroy(private_mysql_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *mysql_plugin_create()
{
private_mysql_plugin_t *this;
if (!mysql_database_init())
{
- DBG1("MySQL client library initialization failed");
+ DBG1(DBG_LIB, "MySQL client library initialization failed");
return NULL;
}
diff --git a/src/libstrongswan/plugins/mysql/mysql_plugin.h b/src/libstrongswan/plugins/mysql/mysql_plugin.h
index fa53c2b7a..d1f21870c 100644
--- a/src/libstrongswan/plugins/mysql/mysql_plugin.h
+++ b/src/libstrongswan/plugins/mysql/mysql_plugin.h
@@ -39,9 +39,4 @@ struct mysql_plugin_t {
plugin_t plugin;
};
-/**
- * Create a mysql_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** MYSQL_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index 25cc5aa1d..a50799798 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -3,12 +3,18 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-openssl.la
+else
plugin_LTLIBRARIES = libstrongswan-openssl.la
+endif
-libstrongswan_openssl_la_SOURCES = openssl_plugin.h openssl_plugin.c \
+libstrongswan_openssl_la_SOURCES = \
+ openssl_plugin.h openssl_plugin.c \
openssl_util.c openssl_util.h \
openssl_crypter.c openssl_crypter.h \
openssl_hasher.c openssl_hasher.h \
+ openssl_sha1_prf.c openssl_sha1_prf.h \
openssl_diffie_hellman.c openssl_diffie_hellman.h \
openssl_rsa_private_key.c openssl_rsa_private_key.h \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index aa8ecf06c..a2a931d42 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -72,18 +72,22 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_openssl_la_DEPENDENCIES =
am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
openssl_util.lo openssl_crypter.lo openssl_hasher.lo \
- openssl_diffie_hellman.lo openssl_rsa_private_key.lo \
- openssl_rsa_public_key.lo openssl_ec_diffie_hellman.lo \
- openssl_ec_private_key.lo openssl_ec_public_key.lo
+ openssl_sha1_prf.lo openssl_diffie_hellman.lo \
+ openssl_rsa_private_key.lo openssl_rsa_public_key.lo \
+ openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \
+ openssl_ec_public_key.lo
libstrongswan_openssl_la_OBJECTS = \
$(am_libstrongswan_openssl_la_OBJECTS)
libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_openssl_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_openssl_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_openssl_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -222,6 +226,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -258,11 +263,14 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-openssl.la
-libstrongswan_openssl_la_SOURCES = openssl_plugin.h openssl_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-openssl.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-openssl.la
+libstrongswan_openssl_la_SOURCES = \
+ openssl_plugin.h openssl_plugin.c \
openssl_util.c openssl_util.h \
openssl_crypter.c openssl_crypter.h \
openssl_hasher.c openssl_hasher.h \
+ openssl_sha1_prf.c openssl_sha1_prf.h \
openssl_diffie_hellman.c openssl_diffie_hellman.h \
openssl_rsa_private_key.c openssl_rsa_private_key.h \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
@@ -306,6 +314,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -338,7 +355,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-openssl.la: $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_DEPENDENCIES)
- $(libstrongswan_openssl_la_LINK) -rpath $(plugindir) $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_LIBADD) $(LIBS)
+ $(libstrongswan_openssl_la_LINK) $(am_libstrongswan_openssl_la_rpath) $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -355,6 +372,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_private_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_util.Plo@am__quote@
.c.o:
@@ -500,8 +518,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -572,18 +590,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
index 80a1ee878..9a032c54f 100644
--- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -20,47 +20,6 @@
#include <debug.h>
-typedef struct modulus_entry_t modulus_entry_t;
-
-/**
- * Entry of the modulus list.
- */
-struct modulus_entry_t {
- /**
- * Group number as it is defined in file transform_substructure.h.
- */
- diffie_hellman_group_t group;
-
- /**
- * Pointer to the function to get the modulus.
- */
- BIGNUM *(*get_prime)(BIGNUM *bn);
-
- /*
- * Optimum length of exponent in bits.
- */
- long opt_exponent_len;
-
- /*
- * Generator value.
- */
- u_int16_t generator;
-};
-
-/**
- * All supported modulus values - optimum exponent size according to RFC 3526.
- */
-static modulus_entry_t modulus_entries[] = {
- {MODP_768_BIT, get_rfc2409_prime_768, 256, 2},
- {MODP_1024_BIT, get_rfc2409_prime_1024, 256, 2},
- {MODP_1536_BIT, get_rfc3526_prime_1536, 256, 2},
- {MODP_2048_BIT, get_rfc3526_prime_2048, 384, 2},
- {MODP_3072_BIT, get_rfc3526_prime_3072, 384, 2},
- {MODP_4096_BIT, get_rfc3526_prime_4096, 512, 2},
- {MODP_6144_BIT, get_rfc3526_prime_6144, 512, 2},
- {MODP_8192_BIT, get_rfc3526_prime_8192, 512, 2},
-};
-
typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
/**
@@ -125,7 +84,6 @@ static status_t get_shared_secret(private_openssl_diffie_hellman_t *this,
memset(secret->ptr, 0, secret->len);
memcpy(secret->ptr + secret->len - this->shared_secret.len,
this->shared_secret.ptr, this->shared_secret.len);
-
return SUCCESS;
}
@@ -145,7 +103,7 @@ static void set_other_public_value(private_openssl_diffie_hellman_t *this,
len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
if (len < 0)
{
- DBG1("DH shared secret computation failed");
+ DBG1(DBG_LIB, "DH shared secret computation failed");
return;
}
this->shared_secret.len = len;
@@ -165,27 +123,18 @@ static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *thi
*/
static status_t set_modulus(private_openssl_diffie_hellman_t *this)
{
- int i;
- bool ansi_x9_42;
-
- ansi_x9_42 = lib->settings->get_bool(lib->settings,
- "libstrongswan.dh_exponent_ansi_x9_42", TRUE);
-
- for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
+ diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
+ if (!params)
{
- if (modulus_entries[i].group == this->group)
- {
- this->dh->p = modulus_entries[i].get_prime(NULL);
- this->dh->g = BN_new();
- BN_set_word(this->dh->g, modulus_entries[i].generator);
- if (!ansi_x9_42)
- {
- this->dh->length = modulus_entries[i].opt_exponent_len;
- }
- return SUCCESS;
- }
+ return NOT_FOUND;
}
- return NOT_FOUND;
+ this->dh->p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL);
+ this->dh->g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL);
+ if (params->exp_len != params->prime.len)
+ {
+ this->dh->length = params->exp_len * 8;
+ }
+ return SUCCESS;
}
/**
@@ -237,7 +186,8 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g
destroy(this);
return NULL;
}
- DBG2("size of DH secret exponent: %d bits", BN_num_bits(this->dh->priv_key));
+ DBG2(DBG_LIB, "size of DH secret exponent: %d bits",
+ BN_num_bits(this->dh->priv_key));
return &this->public;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index 671fa41e2..faec411cd 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -212,14 +212,14 @@ static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, ch
{
if (!chunk2ecp(this->ec_group, value, this->pub_key))
{
- DBG1("ECDH public value is malformed");
+ DBG1(DBG_LIB, "ECDH public value is malformed");
return;
}
chunk_free(&this->shared_secret);
if (!compute_shared_key(this, &this->shared_secret)) {
- DBG1("ECDH shared secret computation failed");
+ DBG1(DBG_LIB, "ECDH shared secret computation failed");
return;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
index 89ced5a9a..bdcfda974 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
@@ -84,14 +84,14 @@ static bool build_curve_signature(private_openssl_ec_private_key_t *this,
req_group = EC_GROUP_new_by_curve_name(nid_curve);
if (!req_group)
{
- DBG1("signature scheme %N not supported in EC (required curve "
+ DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
"not supported)", signature_scheme_names, scheme);
return FALSE;
}
my_group = EC_KEY_get0_group(this->ec);
if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
{
- DBG1("signature scheme %N not supported by private key",
+ DBG1(DBG_LIB, "signature scheme %N not supported by private key",
signature_scheme_names, scheme);
return FALSE;
}
@@ -162,7 +162,7 @@ static bool sign(private_openssl_ec_private_key_t *this,
return build_curve_signature(this, scheme, NID_sha512,
NID_secp521r1, data, signature);
default:
- DBG1("signature scheme %N not supported",
+ DBG1(DBG_LIB, "signature scheme %N not supported",
signature_scheme_names, scheme);
return FALSE;
}
@@ -174,7 +174,7 @@ static bool sign(private_openssl_ec_private_key_t *this,
static bool decrypt(private_openssl_ec_private_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("EC private key decryption not implemented");
+ DBG1(DBG_LIB, "EC private key decryption not implemented");
return FALSE;
}
@@ -233,11 +233,24 @@ static bool get_encoding(private_openssl_ec_private_key_t *this,
switch (type)
{
case KEY_PRIV_ASN1_DER:
+ case KEY_PRIV_PEM:
{
+ bool success = TRUE;
+
*encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
p = encoding->ptr;
i2d_ECPrivateKey(this->ec, &p);
- return TRUE;
+
+ if (type == KEY_PRIV_PEM)
+ {
+ chunk_t asn1_encoding = *encoding;
+
+ success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
+ NULL, encoding, KEY_PART_ECDSA_PRIV_ASN1_DER,
+ asn1_encoding, KEY_PART_END);
+ chunk_clear(&asn1_encoding);
+ }
+ return success;
}
default:
return FALSE;
@@ -335,13 +348,13 @@ openssl_ec_private_key_t *openssl_ec_private_key_gen(key_type_t type,
this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
break;
default:
- DBG1("EC private key size %d not supported", key_size);
+ DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
destroy(this);
return NULL;
}
if (EC_KEY_generate_key(this->ec) != 1)
{
- DBG1("EC private key generation failed", key_size);
+ DBG1(DBG_LIB, "EC private key generation failed", key_size);
destroy(this);
return NULL;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
index f37c736b1..790a8487d 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
@@ -82,14 +82,14 @@ static bool verify_curve_signature(private_openssl_ec_public_key_t *this,
req_group = EC_GROUP_new_by_curve_name(nid_curve);
if (!req_group)
{
- DBG1("signature scheme %N not supported in EC (required curve "
+ DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
"not supported)", signature_scheme_names, scheme);
return FALSE;
}
my_group = EC_KEY_get0_group(this->ec);
if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
{
- DBG1("signature scheme %N not supported by private key",
+ DBG1(DBG_LIB, "signature scheme %N not supported by private key",
signature_scheme_names, scheme);
return FALSE;
}
@@ -162,7 +162,7 @@ static bool verify(private_openssl_ec_public_key_t *this,
return verify_curve_signature(this, scheme, NID_sha512,
NID_secp521r1, data, signature);
default:
- DBG1("signature scheme %N not supported in EC",
+ DBG1(DBG_LIB, "signature scheme %N not supported in EC",
signature_scheme_names, scheme);
return FALSE;
}
@@ -174,7 +174,7 @@ static bool verify(private_openssl_ec_public_key_t *this,
static bool encrypt_(private_openssl_ec_public_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("EC public key encryption not implemented");
+ DBG1(DBG_LIB, "EC public key encryption not implemented");
return FALSE;
}
@@ -217,7 +217,7 @@ bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
- DBG1("SHA1 hash algorithm not supported, fingerprinting failed");
+ DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
free(key.ptr);
return FALSE;
}
@@ -248,11 +248,24 @@ static bool get_encoding(private_openssl_ec_public_key_t *this,
switch (type)
{
case KEY_PUB_SPKI_ASN1_DER:
+ case KEY_PUB_PEM:
{
+ bool success = TRUE;
+
*encoding = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
p = encoding->ptr;
i2d_EC_PUBKEY(this->ec, &p);
- return TRUE;
+
+ if (type == KEY_PUB_PEM)
+ {
+ chunk_t asn1_encoding = *encoding;
+
+ success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
+ NULL, encoding, KEY_PART_ECDSA_PUB_ASN1_DER,
+ asn1_encoding, KEY_PART_END);
+ chunk_clear(&asn1_encoding);
+ }
+ return success;
}
default:
return FALSE;
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index 548a76bb4..c1545ffb8 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -27,6 +27,7 @@
#include "openssl_util.h"
#include "openssl_crypter.h"
#include "openssl_hasher.h"
+#include "openssl_sha1_prf.h"
#include "openssl_diffie_hellman.h"
#include "openssl_ec_diffie_hellman.h"
#include "openssl_rsa_private_key.h"
@@ -170,6 +171,8 @@ static void destroy(private_openssl_plugin_t *this)
(crypter_constructor_t)openssl_crypter_create);
lib->crypto->remove_hasher(lib->crypto,
(hasher_constructor_t)openssl_hasher_create);
+ lib->crypto->remove_prf(lib->crypto,
+ (prf_constructor_t)openssl_sha1_prf_create);
lib->crypto->remove_dh(lib->crypto,
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->remove_dh(lib->crypto,
@@ -201,7 +204,7 @@ static void destroy(private_openssl_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *openssl_plugin_create()
{
private_openssl_plugin_t *this = malloc_thing(private_openssl_plugin_t);
@@ -256,9 +259,17 @@ plugin_t *plugin_create()
lib->crypto->add_hasher(lib->crypto, HASH_SHA512,
(hasher_constructor_t)openssl_hasher_create);
+ /* prf */
+ lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1,
+ (prf_constructor_t)openssl_sha1_prf_create);
+
/* (ec) diffie hellman */
lib->crypto->add_dh(lib->crypto, MODP_2048_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_224,
+ (dh_constructor_t)openssl_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_2048_256,
+ (dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1536_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, ECP_256_BIT,
@@ -281,6 +292,8 @@ plugin_t *plugin_create()
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1024_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
+ lib->crypto->add_dh(lib->crypto, MODP_1024_160,
+ (dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_768_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.h b/src/libstrongswan/plugins/openssl/openssl_plugin.h
index 9f422c9d0..0762c37b9 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.h
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.h
@@ -39,9 +39,4 @@ struct openssl_plugin_t {
plugin_t plugin;
};
-/**
- * Create a openssl_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** OPENSSL_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index 078f889a6..de751fe89 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -160,7 +160,7 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch
case SIGN_RSA_EMSA_PKCS1_MD5:
return build_emsa_pkcs1_signature(this, NID_md5, data, signature);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -172,7 +172,7 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch
static bool decrypt(private_openssl_rsa_private_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("RSA private key decryption not implemented");
+ DBG1(DBG_LIB, "RSA private key decryption not implemented");
return FALSE;
}
@@ -226,11 +226,24 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this,
switch (type)
{
case KEY_PRIV_ASN1_DER:
+ case KEY_PRIV_PEM:
{
+ bool success = TRUE;
+
*encoding = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL));
p = encoding->ptr;
i2d_RSAPrivateKey(this->rsa, &p);
- return TRUE;
+
+ if (type == KEY_PRIV_PEM)
+ {
+ chunk_t asn1_encoding = *encoding;
+
+ success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
+ NULL, encoding, KEY_PART_RSA_PRIV_ASN1_DER,
+ asn1_encoding, KEY_PART_END);
+ chunk_clear(&asn1_encoding);
+ }
+ return success;
}
default:
return FALSE;
@@ -296,6 +309,8 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_gen(key_type_t type,
{
private_openssl_rsa_private_key_t *this;
u_int key_size = 0;
+ RSA *rsa = NULL;
+ BIGNUM *e = NULL;
while (TRUE)
{
@@ -315,10 +330,31 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_gen(key_type_t type,
{
return NULL;
}
+ e = BN_new();
+ if (!e || !BN_set_word(e, PUBLIC_EXPONENT))
+ {
+ goto error;
+ }
+ rsa = RSA_new();
+ if (!rsa || !RSA_generate_key_ex(rsa, key_size, e, NULL))
+ {
+ goto error;
+ }
this = create_empty();
- this->rsa = RSA_generate_key(key_size, PUBLIC_EXPONENT, NULL, NULL);
-
+ this->rsa = rsa;
+ BN_free(e);
return &this->public;
+
+error:
+ if (e)
+ {
+ BN_free(e);
+ }
+ if (rsa)
+ {
+ RSA_free(rsa);
+ }
+ return NULL;
}
/**
@@ -440,22 +476,22 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
}
engine_id = lib->settings->get_str(lib->settings,
- "library.plugins.openssl.engine_id", "pkcs11");
+ "libstrongswan.plugins.openssl.engine_id", "pkcs11");
engine = ENGINE_by_id(engine_id);
if (!engine)
{
- DBG1("engine '%s' is not available", engine_id);
+ DBG1(DBG_LIB, "engine '%s' is not available", engine_id);
return NULL;
}
if (!ENGINE_init(engine))
{
- DBG1("failed to initialize engine '%s'", engine_id);
+ DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id);
ENGINE_free(engine);
return NULL;
}
if (!ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0))
{
- DBG1("failed to set PIN on engine '%s'", engine_id);
+ DBG1(DBG_LIB, "failed to set PIN on engine '%s'", engine_id);
ENGINE_free(engine);
return NULL;
}
@@ -463,8 +499,8 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
key = ENGINE_load_private_key(engine, keyid, NULL, NULL);
if (!key)
{
- DBG1("failed to load private key with ID '%s' from engine '%s'",
- keyid, engine_id);
+ DBG1(DBG_LIB, "failed to load private key with ID '%s' from "
+ "engine '%s'", keyid, engine_id);
ENGINE_free(engine);
return NULL;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index 422262b19..ffa575a97 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -145,7 +145,7 @@ static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t sc
case SIGN_RSA_EMSA_PKCS1_MD5:
return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
default:
- DBG1("signature scheme %N not supported in RSA",
+ DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
return FALSE;
}
@@ -157,7 +157,7 @@ static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t sc
static bool encrypt_(private_openssl_rsa_public_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("RSA public key encryption not implemented");
+ DBG1(DBG_LIB, "RSA public key encryption not implemented");
return FALSE;
}
@@ -200,7 +200,7 @@ bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
- DBG1("SHA1 hash algorithm not supported, fingerprinting failed");
+ DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
free(key.ptr);
return FALSE;
}
@@ -231,11 +231,24 @@ static bool get_encoding(private_openssl_rsa_public_key_t *this,
switch (type)
{
case KEY_PUB_SPKI_ASN1_DER:
+ case KEY_PUB_PEM:
{
+ bool success = TRUE;
+
*encoding = chunk_alloc(i2d_RSA_PUBKEY(this->rsa, NULL));
p = encoding->ptr;
i2d_RSA_PUBKEY(this->rsa, &p);
- return TRUE;
+
+ if (type == KEY_PUB_PEM)
+ {
+ chunk_t asn1_encoding = *encoding;
+
+ success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
+ NULL, encoding, KEY_PART_RSA_PUB_ASN1_DER,
+ asn1_encoding, KEY_PART_END);
+ chunk_clear(&asn1_encoding);
+ }
+ return success;
}
case KEY_PUB_ASN1_DER:
{
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
new file mode 100644
index 000000000..b65388010
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 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 "openssl_sha1_prf.h"
+
+#include <openssl/sha.h>
+
+typedef struct private_openssl_sha1_prf_t private_openssl_sha1_prf_t;
+
+/**
+ * Private data of an openssl_sha1_prf_t object.
+ */
+struct private_openssl_sha1_prf_t {
+
+ /**
+ * Public openssl_sha1_prf_t interface.
+ */
+ openssl_sha1_prf_t public;
+
+ /**
+ * SHA1 context
+ */
+ SHA_CTX ctx;
+};
+
+METHOD(prf_t, get_bytes, void,
+ private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
+{
+ SHA1_Update(&this->ctx, seed.ptr, seed.len);
+
+ if (bytes)
+ {
+ u_int32_t *hash = (u_int32_t*)bytes;
+
+ hash[0] = htonl(this->ctx.h0);
+ hash[1] = htonl(this->ctx.h1);
+ hash[2] = htonl(this->ctx.h2);
+ hash[3] = htonl(this->ctx.h3);
+ hash[4] = htonl(this->ctx.h4);
+ }
+}
+
+METHOD(prf_t, get_block_size, size_t,
+ private_openssl_sha1_prf_t *this)
+{
+ return HASH_SIZE_SHA1;
+}
+
+METHOD(prf_t, allocate_bytes, void,
+ private_openssl_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ *chunk = chunk_alloc(HASH_SIZE_SHA1);
+ get_bytes(this, seed, chunk->ptr);
+ }
+ else
+ {
+ get_bytes(this, seed, NULL);
+ }
+}
+
+METHOD(prf_t, get_key_size, size_t,
+ private_openssl_sha1_prf_t *this)
+{
+ return HASH_SIZE_SHA1;
+}
+
+METHOD(prf_t, set_key, void,
+ private_openssl_sha1_prf_t *this, chunk_t key)
+{
+ SHA1_Init(&this->ctx);
+
+ if (key.len >= 4)
+ {
+ this->ctx.h0 ^= untoh32(key.ptr);
+ }
+ if (key.len >= 8)
+ {
+ this->ctx.h1 ^= untoh32(key.ptr + 4);
+ }
+ if (key.len >= 12)
+ {
+ this->ctx.h2 ^= untoh32(key.ptr + 8);
+ }
+ if (key.len >= 16)
+ {
+ this->ctx.h3 ^= untoh32(key.ptr + 12);
+ }
+ if (key.len >= 20)
+ {
+ this->ctx.h4 ^= untoh32(key.ptr + 16);
+ }
+}
+
+METHOD(prf_t, destroy, void,
+ private_openssl_sha1_prf_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo)
+{
+ private_openssl_sha1_prf_t *this;
+
+ if (algo != PRF_KEYED_SHA1)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public.prf = {
+ .get_block_size = _get_block_size,
+ .get_bytes = _get_bytes,
+ .allocate_bytes = _allocate_bytes,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
new file mode 100644
index 000000000..9a24e7ee1
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 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 openssl_sha1_prf openssl_sha1_prf
+ * @{ @ingroup sha1_p
+ */
+
+#ifndef OPENSSL_SHA1_PRF_H_
+#define OPENSSL_SHA1_PRF_H_
+
+typedef struct openssl_sha1_prf_t openssl_sha1_prf_t;
+
+#include <crypto/prfs/prf.h>
+
+/**
+ * Implementation of prf_t interface using keyed SHA1 algorithm as used
+ * in EAP-AKA/FIPS_PRF.
+ */
+struct openssl_sha1_prf_t {
+
+ /**
+ * Implements prf_t interface.
+ */
+ prf_t prf;
+};
+
+/**
+ * Creates a new openssl_sha1_prf_t.
+ *
+ * @param algo algorithm, must be PRF_KEYED_SHA1
+ * @return sha1_keyed_prf_tobject
+ */
+openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo);
+
+#endif /** OPENSSL_SHA1_PRF_H_ @}*/
diff --git a/src/libstrongswan/plugins/padlock/Makefile.am b/src/libstrongswan/plugins/padlock/Makefile.am
index b2b1f9d85..6706d26cb 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.am
+++ b/src/libstrongswan/plugins/padlock/Makefile.am
@@ -3,11 +3,16 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-padlock.la
+else
plugin_LTLIBRARIES = libstrongswan-padlock.la
+endif
-libstrongswan_padlock_la_SOURCES = padlock_plugin.h padlock_plugin.c \
+libstrongswan_padlock_la_SOURCES = \
+ padlock_plugin.h padlock_plugin.c \
padlock_aes_crypter.c padlock_aes_crypter.h \
padlock_sha1_hasher.c padlock_sha1_hasher.h \
padlock_rng.c padlock_rng.h
-libstrongswan_padlock_la_LDFLAGS = -module -avoid-version
+libstrongswan_padlock_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in
index 59ea98799..84c2ef2fb 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.in
+++ b/src/libstrongswan/plugins/padlock/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_padlock_la_LIBADD =
am_libstrongswan_padlock_la_OBJECTS = padlock_plugin.lo \
padlock_aes_crypter.lo padlock_sha1_hasher.lo padlock_rng.lo
@@ -81,6 +81,9 @@ libstrongswan_padlock_la_OBJECTS = \
libstrongswan_padlock_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_padlock_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_padlock_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_padlock_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -219,6 +222,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -255,8 +259,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-padlock.la
-libstrongswan_padlock_la_SOURCES = padlock_plugin.h padlock_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-padlock.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-padlock.la
+libstrongswan_padlock_la_SOURCES = \
+ padlock_plugin.h padlock_plugin.c \
padlock_aes_crypter.c padlock_aes_crypter.h \
padlock_sha1_hasher.c padlock_sha1_hasher.h \
padlock_rng.c padlock_rng.h
@@ -296,6 +302,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -328,7 +343,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-padlock.la: $(libstrongswan_padlock_la_OBJECTS) $(libstrongswan_padlock_la_DEPENDENCIES)
- $(libstrongswan_padlock_la_LINK) -rpath $(plugindir) $(libstrongswan_padlock_la_OBJECTS) $(libstrongswan_padlock_la_LIBADD) $(LIBS)
+ $(libstrongswan_padlock_la_LINK) $(am_libstrongswan_padlock_la_rpath) $(libstrongswan_padlock_la_OBJECTS) $(libstrongswan_padlock_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -484,8 +499,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -556,18 +571,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c
index 32b18ec4b..c9606ae15 100644
--- a/src/libstrongswan/plugins/padlock/padlock_plugin.c
+++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c
@@ -97,7 +97,7 @@ static padlock_feature_t get_padlock_features()
return d;
}
}
- DBG1("Padlock not found, CPU is %s", vendor);
+ DBG1(DBG_LIB, "Padlock not found, CPU is %s", vendor);
return 0;
}
@@ -131,7 +131,7 @@ static void destroy(private_padlock_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *padlock_plugin_create()
{
private_padlock_plugin_t *this = malloc_thing(private_padlock_plugin_t);
@@ -143,7 +143,7 @@ plugin_t *plugin_create()
free(this);
return NULL;
}
- DBG1("Padlock found, supports:%s%s%s%s%s, enabled:%s%s%s%s%s",
+ DBG1(DBG_LIB, "Padlock found, supports:%s%s%s%s%s, enabled:%s%s%s%s%s",
this->features & PADLOCK_RNG_AVAILABLE ? " RNG" : "",
this->features & PADLOCK_ACE_AVAILABLE ? " ACE" : "",
this->features & PADLOCK_ACE2_AVAILABLE ? " ACE2" : "",
diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.h b/src/libstrongswan/plugins/padlock/padlock_plugin.h
index 76f4d1135..d99d4db0f 100644
--- a/src/libstrongswan/plugins/padlock/padlock_plugin.h
+++ b/src/libstrongswan/plugins/padlock/padlock_plugin.h
@@ -39,9 +39,4 @@ struct padlock_plugin_t {
plugin_t plugin;
};
-/**
- * Create a padlock_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** PADLOCK_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/pem/Makefile.am b/src/libstrongswan/plugins/pem/Makefile.am
index 98f356aaf..b815b1e0b 100644
--- a/src/libstrongswan/plugins/pem/Makefile.am
+++ b/src/libstrongswan/plugins/pem/Makefile.am
@@ -3,10 +3,15 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-pem.la
+else
plugin_LTLIBRARIES = libstrongswan-pem.la
+endif
-libstrongswan_pem_la_SOURCES = pem_plugin.h pem_plugin.c \
- pem_builder.c pem_builder.h
+libstrongswan_pem_la_SOURCES = \
+ pem_plugin.h pem_plugin.c \
+ pem_builder.c pem_builder.h \
+ pem_encoder.c pem_encoder.h
libstrongswan_pem_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in
index e81b4f78f..4e39c8f7b 100644
--- a/src/libstrongswan/plugins/pem/Makefile.in
+++ b/src/libstrongswan/plugins/pem/Makefile.in
@@ -72,13 +72,16 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_pem_la_LIBADD =
-am_libstrongswan_pem_la_OBJECTS = pem_plugin.lo pem_builder.lo
+am_libstrongswan_pem_la_OBJECTS = pem_plugin.lo pem_builder.lo \
+ pem_encoder.lo
libstrongswan_pem_la_OBJECTS = $(am_libstrongswan_pem_la_OBJECTS)
libstrongswan_pem_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_pem_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_pem_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_pem_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,9 +257,12 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-pem.la
-libstrongswan_pem_la_SOURCES = pem_plugin.h pem_plugin.c \
- pem_builder.c pem_builder.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-pem.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-pem.la
+libstrongswan_pem_la_SOURCES = \
+ pem_plugin.h pem_plugin.c \
+ pem_builder.c pem_builder.h \
+ pem_encoder.c pem_encoder.h
libstrongswan_pem_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -292,6 +299,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -324,7 +340,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-pem.la: $(libstrongswan_pem_la_OBJECTS) $(libstrongswan_pem_la_DEPENDENCIES)
- $(libstrongswan_pem_la_LINK) -rpath $(plugindir) $(libstrongswan_pem_la_OBJECTS) $(libstrongswan_pem_la_LIBADD) $(LIBS)
+ $(libstrongswan_pem_la_LINK) $(am_libstrongswan_pem_la_rpath) $(libstrongswan_pem_la_OBJECTS) $(libstrongswan_pem_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -333,6 +349,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem_builder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem_encoder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem_plugin.Plo@am__quote@
.c.o:
@@ -478,8 +495,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -550,18 +567,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index 2f285e9bc..65be9501b 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -73,7 +73,7 @@ static bool find_boundary(char* tag, chunk_t *line)
{
if (present("-----", line))
{
- DBG2(" -----%s %.*s-----", tag, (int)name.len, name.ptr);
+ DBG2(DBG_LIB, " -----%s %.*s-----", tag, (int)name.len, name.ptr);
return TRUE;
}
line->ptr++; line->len--; name.len++;
@@ -99,7 +99,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
if (hasher == NULL)
{
- DBG1(" MD5 hash algorithm not available");
+ DBG1(DBG_LIB, " MD5 hash algorithm not available");
return NOT_SUPPORTED;
}
hash.len = hasher->get_hash_size(hasher);
@@ -121,7 +121,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
if (crypter == NULL)
{
- DBG1(" %N encryption algorithm not available",
+ DBG1(DBG_LIB, " %N encryption algorithm not available",
encryption_algorithm_names, alg);
return NOT_SUPPORTED;
}
@@ -131,7 +131,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
blob->len % iv.len)
{
crypter->destroy(crypter);
- DBG1(" data size is not multiple of block size");
+ DBG1(DBG_LIB, " data size is not multiple of block size");
return PARSE_ERROR;
}
crypter->decrypt(crypter, *blob, iv, &decrypted);
@@ -155,7 +155,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
{
if (*last_padding_pos != padding)
{
- DBG1(" invalid passphrase");
+ DBG1(DBG_LIB, " invalid passphrase");
return INVALID_ARG;
}
}
@@ -234,7 +234,7 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
}
/* we are looking for a parameter: value pair */
- DBG2(" %.*s", (int)line.len, line.ptr);
+ DBG2(DBG_LIB, " %.*s", (int)line.len, line.ptr);
ugh = extract_parameter_value(&name, &value, &line);
if (ugh != NULL)
{
@@ -274,8 +274,8 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
}
else
{
- DBG1(" encryption algorithm '%.*s' not supported",
- dek.len, dek.ptr);
+ DBG1(DBG_LIB, " encryption algorithm '%.*s'"
+ " not supported", dek.len, dek.ptr);
return NOT_SUPPORTED;
}
eat_whitespace(&value);
@@ -298,7 +298,8 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
*pgp = TRUE;
data.ptr++;
data.len--;
- DBG2(" armor checksum: %.*s", (int)data.len, data.ptr);
+ DBG2(DBG_LIB, " armor checksum: %.*s", (int)data.len,
+ data.ptr);
continue;
}
@@ -318,7 +319,7 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
if (state != PEM_POST)
{
- DBG1(" file coded in unknown format, discarded");
+ DBG1(DBG_LIB, " file coded in unknown format, discarded");
return PARSE_ERROR;
}
if (!encrypted)
@@ -327,7 +328,7 @@ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data
}
if (!cb)
{
- DBG1(" missing passphrase");
+ DBG1(DBG_LIB, " missing passphrase");
return INVALID_ARG;
}
while (TRUE)
@@ -404,13 +405,14 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
fd = open(file, O_RDONLY);
if (fd == -1)
{
- DBG1(" opening '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " opening '%s' failed: %s", file, strerror(errno));
return NULL;
}
if (fstat(fd, &sb) == -1)
{
- DBG1(" getting file size of '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " getting file size of '%s' failed: %s", file,
+ strerror(errno));
close(fd);
return NULL;
}
@@ -418,7 +420,7 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
- DBG1(" mapping '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_LIB, " mapping '%s' failed: %s", file, strerror(errno));
close(fd);
return NULL;
}
@@ -447,7 +449,8 @@ static void *load_from_fd(int fd, credential_type_t type, int subtype,
len = read(fd, pos, buf + sizeof(buf) - pos);
if (len < 0)
{
- DBG1("reading from file descriptor failed: %s", strerror(errno));
+ DBG1(DBG_LIB, "reading from file descriptor failed: %s",
+ strerror(errno));
return NULL;
}
if (len == 0)
@@ -457,7 +460,7 @@ static void *load_from_fd(int fd, credential_type_t type, int subtype,
total += len;
if (total == sizeof(buf))
{
- DBG1("buffer too small to read from file descriptor");
+ DBG1(DBG_LIB, "buffer too small to read from file descriptor");
return NULL;
}
}
diff --git a/src/libstrongswan/plugins/pem/pem_builder.h b/src/libstrongswan/plugins/pem/pem_builder.h
index 189a5430f..87f5a2c69 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.h
+++ b/src/libstrongswan/plugins/pem/pem_builder.h
@@ -18,8 +18,8 @@
* @{ @ingroup pem_p
*/
-#ifndef PEM_PRIVATE_KEY_H_
-#define PEM_PRIVATE_KEY_H_
+#ifndef PEM_BUILDER_H_
+#define PEM_BUILDER_H_
#include <credentials/builder.h>
#include <credentials/credential_factory.h>
@@ -53,5 +53,5 @@ public_key_t *pem_public_key_load(key_type_t type, va_list args);
*/
certificate_t *pem_certificate_load(certificate_type_t type, va_list args);
-#endif /** PEM_PRIVATE_KEY_H_ @}*/
+#endif /** PEM_BUILDER_H_ @}*/
diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c
new file mode 100644
index 000000000..13c99a958
--- /dev/null
+++ b/src/libstrongswan/plugins/pem/pem_encoder.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pem_encoder.h"
+
+#define BYTES_PER_LINE 48
+
+/**
+ * See header.
+ */
+bool pem_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+ va_list args)
+{
+ chunk_t asn1;
+ char *label;
+ u_char *pos;
+ size_t len, written, pem_chars, pem_lines;
+ chunk_t n, e, d, p, q, exp1, exp2, coeff, to_free = chunk_empty;
+
+ switch (type)
+ {
+ case KEY_PUB_PEM:
+ label ="PUBLIC KEY";
+ /* direct PKCS#1 PEM encoding */
+ if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER,
+ &asn1, KEY_PART_END) ||
+ key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER,
+ &asn1, KEY_PART_END))
+ {
+ break;
+ }
+ /* indirect PEM encoding from components */
+ if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
+ KEY_PART_RSA_PUB_EXP, &e, KEY_PART_END))
+ {
+ if (lib->encoding->encode(lib->encoding, KEY_PUB_SPKI_ASN1_DER,
+ NULL, &asn1, KEY_PART_RSA_MODULUS, n,
+ KEY_PART_RSA_PUB_EXP, e, KEY_PART_END))
+ {
+ to_free = asn1;
+ break;
+ }
+ }
+ return FALSE;
+ case KEY_PRIV_PEM:
+ label ="RSA PRIVATE KEY";
+ /* direct PKCS#1 PEM encoding */
+ if (key_encoding_args(args, KEY_PART_RSA_PRIV_ASN1_DER,
+ &asn1, KEY_PART_END))
+ {
+ break;
+ }
+ /* indirect PEM encoding from components */
+ if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
+ KEY_PART_RSA_PUB_EXP, &e, KEY_PART_RSA_PRIV_EXP, &d,
+ KEY_PART_RSA_PRIME1, &p, KEY_PART_RSA_PRIME2, &q,
+ KEY_PART_RSA_EXP1, &exp1, KEY_PART_RSA_EXP2, &exp2,
+ KEY_PART_RSA_COEFF, &coeff, KEY_PART_END))
+ {
+ if (lib->encoding->encode(lib->encoding, KEY_PRIV_ASN1_DER, NULL,
+ &asn1, KEY_PART_RSA_MODULUS, n,
+ KEY_PART_RSA_PUB_EXP, e, KEY_PART_RSA_PRIV_EXP, d,
+ KEY_PART_RSA_PRIME1, p, KEY_PART_RSA_PRIME2, q,
+ KEY_PART_RSA_EXP1, exp1, KEY_PART_RSA_EXP2, exp2,
+ KEY_PART_RSA_COEFF, coeff, KEY_PART_END))
+ {
+ to_free = asn1;
+ break;
+ }
+ }
+ if (key_encoding_args(args, KEY_PART_ECDSA_PRIV_ASN1_DER,
+ &asn1, KEY_PART_END))
+ {
+ label ="EC PRIVATE KEY";
+ break;
+ }
+ return FALSE;
+ default:
+ return FALSE;
+ }
+
+ /* compute and allocate maximum size of PEM object */
+ pem_chars = 4*(asn1.len + 2)/3;
+ pem_lines = (asn1.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
+ *encoding = chunk_alloc(5 + 2*(6 + strlen(label) + 6) + 3 + pem_chars + pem_lines);
+ pos = encoding->ptr;
+ len = encoding->len;
+
+ /* write PEM header */
+ written = snprintf(pos, len, "-----BEGIN %s-----\n", label);
+ pos += written;
+ len -= written;
+
+ /* write PEM body */
+ while (pem_lines--)
+ {
+ chunk_t asn1_line, pem_line;
+
+ asn1_line = chunk_create(asn1.ptr, min(asn1.len, BYTES_PER_LINE));
+ asn1.ptr += asn1_line.len;
+ asn1.len -= asn1_line.len;
+ pem_line = chunk_to_base64(asn1_line, pos);
+ pos += pem_line.len;
+ len -= pem_line.len;
+ *pos = '\n';
+ pos++;
+ len--;
+ }
+
+ chunk_clear(&to_free);
+
+ /* write PEM trailer */
+ written = snprintf(pos, len, "-----END %s-----", label);
+ pos += written;
+ len -= written;
+
+ /* replace termination null character with newline */
+ *pos = '\n';
+ pos++;
+ len--;
+
+ /* compute effective length of PEM object */
+ encoding->len = pos - encoding->ptr;
+ return TRUE;
+}
+
diff --git a/src/libstrongswan/plugins/pem/pem_encoder.h b/src/libstrongswan/plugins/pem/pem_encoder.h
new file mode 100644
index 000000000..a181133b7
--- /dev/null
+++ b/src/libstrongswan/plugins/pem/pem_encoder.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pem_encoder pem_encoder
+ * @{ @ingroup pem_p
+ */
+
+#ifndef PEM_ENCODER_H_
+#define PEM_ENCODER_H_
+
+#include <credentials/keys/key_encoding.h>
+
+/**
+ * Encoding from ASN.1 to PEM format.
+ */
+bool pem_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+ va_list args);
+
+#endif /** PEM_ENCODER_H_ @}*/
+
diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c
index 5a5149ca8..810901b7a 100644
--- a/src/libstrongswan/plugins/pem/pem_plugin.c
+++ b/src/libstrongswan/plugins/pem/pem_plugin.c
@@ -16,7 +16,9 @@
#include "pem_plugin.h"
#include <library.h>
+
#include "pem_builder.h"
+#include "pem_encoder.h"
typedef struct private_pem_plugin_t private_pem_plugin_t;
@@ -48,7 +50,7 @@ static void destroy(private_pem_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *pem_plugin_create()
{
private_pem_plugin_t *this = malloc_thing(private_pem_plugin_t);
@@ -100,6 +102,9 @@ plugin_t *plugin_create()
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
(builder_function_t)pem_certificate_load);
+ /* register PEM encoder */
+ lib->encoding->add_encoder(lib->encoding, pem_encoder_encode);
+
return &this->public.plugin;
}
diff --git a/src/libstrongswan/plugins/pem/pem_plugin.h b/src/libstrongswan/plugins/pem/pem_plugin.h
index 75616c496..944a3fc85 100644
--- a/src/libstrongswan/plugins/pem/pem_plugin.h
+++ b/src/libstrongswan/plugins/pem/pem_plugin.h
@@ -39,9 +39,4 @@ struct pem_plugin_t {
plugin_t plugin;
};
-/**
- * Create a pem_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** PEM_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/pgp/Makefile.am b/src/libstrongswan/plugins/pgp/Makefile.am
index c232971bb..4b414616d 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.am
+++ b/src/libstrongswan/plugins/pgp/Makefile.am
@@ -3,13 +3,17 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-pgp.la
+else
plugin_LTLIBRARIES = libstrongswan-pgp.la
+endif
-libstrongswan_pgp_la_SOURCES = pgp_plugin.h pgp_plugin.c \
- pgp_utils.h pgp_utils.c \
- pgp_cert.h pgp_cert.c \
- pgp_encoder.h pgp_encoder.c \
- pgp_builder.h pgp_builder.c
+libstrongswan_pgp_la_SOURCES = \
+ pgp_plugin.h pgp_plugin.c \
+ pgp_utils.h pgp_utils.c \
+ pgp_cert.h pgp_cert.c \
+ pgp_encoder.h pgp_encoder.c \
+ pgp_builder.h pgp_builder.c
libstrongswan_pgp_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in
index 70840c400..5d487364f 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.in
+++ b/src/libstrongswan/plugins/pgp/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_pgp_la_LIBADD =
am_libstrongswan_pgp_la_OBJECTS = pgp_plugin.lo pgp_utils.lo \
pgp_cert.lo pgp_encoder.lo pgp_builder.lo
@@ -80,6 +80,8 @@ libstrongswan_pgp_la_OBJECTS = $(am_libstrongswan_pgp_la_OBJECTS)
libstrongswan_pgp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_pgp_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_pgp_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_pgp_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,12 +257,14 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-pgp.la
-libstrongswan_pgp_la_SOURCES = pgp_plugin.h pgp_plugin.c \
- pgp_utils.h pgp_utils.c \
- pgp_cert.h pgp_cert.c \
- pgp_encoder.h pgp_encoder.c \
- pgp_builder.h pgp_builder.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-pgp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-pgp.la
+libstrongswan_pgp_la_SOURCES = \
+ pgp_plugin.h pgp_plugin.c \
+ pgp_utils.h pgp_utils.c \
+ pgp_cert.h pgp_cert.c \
+ pgp_encoder.h pgp_encoder.c \
+ pgp_builder.h pgp_builder.c
libstrongswan_pgp_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -296,6 +301,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -328,7 +342,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-pgp.la: $(libstrongswan_pgp_la_OBJECTS) $(libstrongswan_pgp_la_DEPENDENCIES)
- $(libstrongswan_pgp_la_LINK) -rpath $(plugindir) $(libstrongswan_pgp_la_OBJECTS) $(libstrongswan_pgp_la_LIBADD) $(LIBS)
+ $(libstrongswan_pgp_la_LINK) $(am_libstrongswan_pgp_la_rpath) $(libstrongswan_pgp_la_OBJECTS) $(libstrongswan_pgp_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -485,8 +499,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -557,18 +571,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.c b/src/libstrongswan/plugins/pgp/pgp_builder.c
index d262d18ff..84c9bfddd 100644
--- a/src/libstrongswan/plugins/pgp/pgp_builder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_builder.c
@@ -41,7 +41,7 @@ static public_key_t *parse_public_key(chunk_t blob)
BUILD_BLOB_PGP, blob, BUILD_END);
break;
default:
- DBG1("PGP public key algorithm %N not supported",
+ DBG1(DBG_LIB, "PGP public key algorithm %N not supported",
pgp_pubkey_alg_names, alg);
return NULL;
}
@@ -90,12 +90,13 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
}
if (s2k == 255 || s2k == 254)
{
- DBG1("string-to-key specifiers not supported");
+ DBG1(DBG_LIB, "string-to-key specifiers not supported");
return NULL;
}
if (s2k != PGP_SYM_ALG_PLAIN)
{
- DBG1("%N private key encryption not supported", pgp_sym_alg_names, s2k);
+ DBG1(DBG_LIB, "%N private key encryption not supported",
+ pgp_sym_alg_names, s2k);
return NULL;
}
@@ -121,7 +122,7 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
static bool sign_not_allowed(private_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t *signature)
{
- DBG1("signing failed - decryption only key");
+ DBG1(DBG_LIB, "signing failed - decryption only key");
return FALSE;
}
@@ -131,7 +132,7 @@ static bool sign_not_allowed(private_key_t *this, signature_scheme_t scheme,
static bool decrypt_not_allowed(private_key_t *this,
chunk_t crypto, chunk_t *plain)
{
- DBG1("decryption failed - signature only key");
+ DBG1(DBG_LIB, "decryption failed - signature only key");
return FALSE;
}
@@ -164,7 +165,7 @@ static private_key_t *parse_private_key(chunk_t blob)
case 4:
break;
default:
- DBG1("PGP packet version V%d not supported", version);
+ DBG1(DBG_LIB, "PGP packet version V%d not supported", version);
return FALSE;
}
if (!pgp_read_scalar(&packet, 4, &created))
diff --git a/src/libstrongswan/plugins/pgp/pgp_cert.c b/src/libstrongswan/plugins/pgp/pgp_cert.c
index fa2612285..cd04f3d1a 100644
--- a/src/libstrongswan/plugins/pgp/pgp_cert.c
+++ b/src/libstrongswan/plugins/pgp/pgp_cert.c
@@ -198,9 +198,9 @@ static bool is_newer(certificate_t *this, certificate_t *that)
this->get_validity(this, &now, &this_update, NULL);
that->get_validity(that, &now, &that_update, NULL);
new = this_update > that_update;
- DBG1(" certificate from %T is %s - existing certificate from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
+ DBG1(DBG_LIB, " certificate from %T is %s - existing certificate"
+ " from %T %s", &this_update, FALSE, new ? "newer" : "not newer",
+ &that_update, FALSE, new ? "replaced" : "retained");
return new;
}
@@ -322,16 +322,18 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
}
break;
default:
- DBG1("PGP packet version V%d not supported", this->version);
+ DBG1(DBG_LIB, "PGP packet version V%d not supported",
+ this->version);
return FALSE;
}
if (this->valid)
{
- DBG2("L2 - created %T, valid %d days", &this->created, FALSE, this->valid);
+ DBG2(DBG_LIB, "L2 - created %T, valid %d days", &this->created, FALSE,
+ this->valid);
}
else
{
- DBG2("L2 - created %T, never expires", &this->created, FALSE);
+ DBG2(DBG_LIB, "L2 - created %T, never expires", &this->created, FALSE);
}
DESTROY_IF(this->key);
this->key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
@@ -352,13 +354,13 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (hasher == NULL)
{
- DBG1("no SHA-1 hasher available");
+ DBG1(DBG_LIB, "no SHA-1 hasher available");
return FALSE;
}
hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint);
hasher->destroy(hasher);
- DBG2("L2 - v4 fingerprint %#B", &this->fingerprint);
+ DBG2(DBG_LIB, "L2 - v4 fingerprint %#B", &this->fingerprint);
}
else
{
@@ -369,7 +371,7 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
return FALSE;
}
this->fingerprint = chunk_clone(this->fingerprint);
- DBG2("L2 - v3 fingerprint %#B", &this->fingerprint);
+ DBG2(DBG_LIB, "L2 - v3 fingerprint %#B", &this->fingerprint);
}
return TRUE;
}
@@ -389,7 +391,7 @@ static bool parse_signature(private_pgp_cert_t *this, chunk_t packet)
/* we parse only v3 or v4 signature packets */
if (version != 3 && version != 4)
{
- DBG2("L2 - v%d signature ignored", version);
+ DBG2(DBG_LIB, "L2 - v%d signature ignored", version);
return TRUE;
}
if (version == 4)
@@ -398,7 +400,7 @@ static bool parse_signature(private_pgp_cert_t *this, chunk_t packet)
{
return FALSE;
}
- DBG2("L2 - v%d signature of type 0x%02x", version, type);
+ DBG2(DBG_LIB, "L2 - v%d signature of type 0x%02x", version, type);
}
else
{
@@ -411,8 +413,8 @@ static bool parse_signature(private_pgp_cert_t *this, chunk_t packet)
{
return FALSE;
}
- DBG2("L2 - v3 signature of type 0x%02x, created %T", type,
- &created, FALSE);
+ DBG2(DBG_LIB, "L2 - v3 signature of type 0x%02x, created %T", type,
+ &created, FALSE);
}
/* TODO: parse and save signature to a list */
return TRUE;
@@ -425,7 +427,7 @@ static bool parse_user_id(private_pgp_cert_t *this, chunk_t packet)
{
DESTROY_IF(this->user_id);
this->user_id = identification_create_from_encoding(ID_KEY_ID, packet);
- DBG2("L2 - '%Y'", this->user_id);
+ DBG2(DBG_LIB, "L2 - '%Y'", this->user_id);
return TRUE;
}
@@ -486,7 +488,7 @@ pgp_cert_t *pgp_cert_load(certificate_type_t type, va_list args)
}
break;
default:
- DBG1("ignoring %N packet in PGP certificate",
+ DBG1(DBG_LIB, "ignoring %N packet in PGP certificate",
pgp_packet_tag_names, tag);
break;
}
diff --git a/src/libstrongswan/plugins/pgp/pgp_encoder.c b/src/libstrongswan/plugins/pgp/pgp_encoder.c
index 56acac597..d5c3df590 100644
--- a/src/libstrongswan/plugins/pgp/pgp_encoder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_encoder.c
@@ -31,7 +31,8 @@ static bool build_v3_fingerprint(chunk_t *encoding, va_list args)
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
if (!hasher)
{
- DBG1("MD5 hash algorithm not supported, PGP fingerprinting failed");
+ DBG1(DBG_LIB, "MD5 hash algorithm not supported, PGP"
+ " fingerprinting failed");
return FALSE;
}
/* remove leading zero bytes before hashing modulus and exponent */
diff --git a/src/libstrongswan/plugins/pgp/pgp_plugin.c b/src/libstrongswan/plugins/pgp/pgp_plugin.c
index eabb3695f..3ed1faf01 100644
--- a/src/libstrongswan/plugins/pgp/pgp_plugin.c
+++ b/src/libstrongswan/plugins/pgp/pgp_plugin.c
@@ -54,7 +54,7 @@ static void destroy(private_pgp_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *pgp_plugin_create()
{
private_pgp_plugin_t *this = malloc_thing(private_pgp_plugin_t);
diff --git a/src/libstrongswan/plugins/pgp/pgp_plugin.h b/src/libstrongswan/plugins/pgp/pgp_plugin.h
index 95765cd76..8a0ab89d6 100644
--- a/src/libstrongswan/plugins/pgp/pgp_plugin.h
+++ b/src/libstrongswan/plugins/pgp/pgp_plugin.h
@@ -39,9 +39,4 @@ struct pgp_plugin_t {
plugin_t plugin;
};
-/**
- * Create a pgp_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** PGP_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/pgp/pgp_utils.c b/src/libstrongswan/plugins/pgp/pgp_utils.c
index 1658f3232..2d85cc0c8 100644
--- a/src/libstrongswan/plugins/pgp/pgp_utils.c
+++ b/src/libstrongswan/plugins/pgp/pgp_utils.c
@@ -79,7 +79,7 @@ bool pgp_read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar)
if (bytes > blob->len)
{
- DBG1("PGP data too short to read %d byte scalar", bytes);
+ DBG1(DBG_LIB, "PGP data too short to read %d byte scalar", bytes);
return FALSE;
}
while (bytes-- > 0)
@@ -100,13 +100,13 @@ bool pgp_read_mpi(chunk_t *blob, chunk_t *mpi)
if (!pgp_read_scalar(blob, 2, &bits))
{
- DBG1("PGP data too short to read MPI length");
+ DBG1(DBG_LIB, "PGP data too short to read MPI length");
return FALSE;
}
bytes = (bits + 7) / 8;
if (bytes > blob->len)
{
- DBG1("PGP data too short to read %d byte MPI", bytes);
+ DBG1(DBG_LIB, "PGP data too short to read %d byte MPI", bytes);
return FALSE;
}
*mpi = chunk_create(blob->ptr, bytes);
@@ -146,7 +146,7 @@ bool pgp_read_packet(chunk_t *blob, chunk_t *data, pgp_packet_tag_t *tag)
if (!blob->len)
{
- DBG1("missing input");
+ DBG1(DBG_LIB, "missing input");
return FALSE;
}
t = blob->ptr[0];
@@ -154,27 +154,27 @@ bool pgp_read_packet(chunk_t *blob, chunk_t *data, pgp_packet_tag_t *tag)
/* bit 7 must be set */
if (!(t & 0x80))
{
- DBG1("invalid packet tag");
+ DBG1(DBG_LIB, "invalid packet tag");
return FALSE;
}
/* bit 6 set defines new packet format */
if (t & 0x40)
{
- DBG1("new PGP packet format not supported");
+ DBG1(DBG_LIB, "new PGP packet format not supported");
return FALSE;
}
t = (t & 0x3C) >> 2;
if (!pgp_old_packet_length(blob, &len) || len > blob->len)
{
- DBG1("invalid packet length");
+ DBG1(DBG_LIB, "invalid packet length");
return FALSE;
}
*data = chunk_create(blob->ptr, len);
*blob = chunk_skip(*blob, len);
*tag = t;
- DBG2("L1 - PGP %N (%u bytes)", pgp_packet_tag_names, t, len);
- DBG3("%B", data);
+ DBG2(DBG_LIB, "L1 - PGP %N (%u bytes)", pgp_packet_tag_names, t, len);
+ DBG3(DBG_LIB, "%B", data);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.am b/src/libstrongswan/plugins/pkcs1/Makefile.am
index 88d25a26b..bd3203dae 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.am
@@ -3,11 +3,15 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-pkcs1.la
+else
plugin_LTLIBRARIES = libstrongswan-pkcs1.la
+endif
-libstrongswan_pkcs1_la_SOURCES = pkcs1_plugin.h pkcs1_plugin.c \
- pkcs1_encoder.h pkcs1_encoder.c \
- pkcs1_builder.h pkcs1_builder.c
+libstrongswan_pkcs1_la_SOURCES = \
+ pkcs1_plugin.h pkcs1_plugin.c \
+ pkcs1_encoder.h pkcs1_encoder.c \
+ pkcs1_builder.h pkcs1_builder.c
libstrongswan_pkcs1_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in
index 4439cd60f..3fdcd0590 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_pkcs1_la_LIBADD =
am_libstrongswan_pkcs1_la_OBJECTS = pkcs1_plugin.lo pkcs1_encoder.lo \
pkcs1_builder.lo
@@ -80,6 +80,9 @@ libstrongswan_pkcs1_la_OBJECTS = $(am_libstrongswan_pkcs1_la_OBJECTS)
libstrongswan_pkcs1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_pkcs1_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_pkcs1_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_pkcs1_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,10 +258,12 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-pkcs1.la
-libstrongswan_pkcs1_la_SOURCES = pkcs1_plugin.h pkcs1_plugin.c \
- pkcs1_encoder.h pkcs1_encoder.c \
- pkcs1_builder.h pkcs1_builder.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-pkcs1.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-pkcs1.la
+libstrongswan_pkcs1_la_SOURCES = \
+ pkcs1_plugin.h pkcs1_plugin.c \
+ pkcs1_encoder.h pkcs1_encoder.c \
+ pkcs1_builder.h pkcs1_builder.c
libstrongswan_pkcs1_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -294,6 +300,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -326,7 +341,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-pkcs1.la: $(libstrongswan_pkcs1_la_OBJECTS) $(libstrongswan_pkcs1_la_DEPENDENCIES)
- $(libstrongswan_pkcs1_la_LINK) -rpath $(plugindir) $(libstrongswan_pkcs1_la_OBJECTS) $(libstrongswan_pkcs1_la_LIBADD) $(LIBS)
+ $(libstrongswan_pkcs1_la_LINK) $(am_libstrongswan_pkcs1_la_rpath) $(libstrongswan_pkcs1_la_OBJECTS) $(libstrongswan_pkcs1_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -481,8 +496,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -553,18 +568,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c
index fbd35e830..88c848899 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c
@@ -81,10 +81,10 @@ static public_key_t *parse_public_key(chunk_t blob)
/* skip initial bit string octet defining 0 unused bits */
object = chunk_skip(object, 1);
}
- DBG2("-- > --");
+ DBG2(DBG_LIB, "-- > --");
key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
BUILD_BLOB_ASN1_DER, object, BUILD_END);
- DBG2("-- < --");
+ DBG2(DBG_LIB, "-- < --");
break;
}
}
@@ -197,7 +197,7 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
case PRIV_KEY_VERSION:
if (object.len > 0 && *object.ptr != 0)
{
- DBG1("PKCS#1 private key format is not version 1");
+ DBG1(DBG_LIB, "PKCS#1 private key format is not version 1");
goto end;
}
break;
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.h b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.h
index 62ca9f351..9f251833e 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.h
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.h
@@ -14,7 +14,7 @@
*/
/**
- * @defgroup pkcs1_public_key pkcs1_public_key
+ * @defgroup pkcs1_builder pkcs1_builder
* @{ @ingroup pkcs1
*/
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
index 0a8da815a..e46062d97 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
@@ -97,7 +97,8 @@ static bool hash_pubkey(chunk_t pubkey, chunk_t *hash)
if (hasher == NULL)
{
chunk_free(&pubkey);
- DBG1("SHA1 hash algorithm not supported, fingerprinting failed");
+ DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
+ "fingerprinting failed");
return FALSE;
}
hasher->allocate_hash(hasher, pubkey, hash);
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c
index 9d71e1388..35ec2d2bf 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c
@@ -50,7 +50,7 @@ static void destroy(private_pkcs1_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *pkcs1_plugin_create()
{
private_pkcs1_plugin_t *this = malloc_thing(private_pkcs1_plugin_t);
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.h b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.h
index 465c7ef2c..588bde559 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.h
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.h
@@ -39,9 +39,4 @@ struct pkcs1_plugin_t {
plugin_t plugin;
};
-/**
- * Create a pkcs1_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** PKCS1_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/plugin.h b/src/libstrongswan/plugins/plugin.h
index 28c800c0c..6d8a370fb 100644
--- a/src/libstrongswan/plugins/plugin.h
+++ b/src/libstrongswan/plugins/plugin.h
@@ -38,9 +38,9 @@ struct plugin_t {
/**
* Plugin constructor function definiton.
*
- * Each plugin has a constructor functions. This function is called on daemon
+ * Each plugin has a constructor function. This function is called on daemon
* startup to initialize each plugin.
- * The plugin function is named plugin_create().
+ * The plugin function is named plugin_name_plugin_create().
*
* @return plugin_t instance
*/
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index d4513f25a..cad279a9d 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -49,37 +50,83 @@ struct private_plugin_loader_t {
linked_list_t *names;
};
+#ifdef MONOLITHIC
+/**
+ * load a single plugin in monolithic mode
+ */
+static plugin_t* load_plugin(private_plugin_loader_t *this,
+ char *path, char *name)
+{
+ char create[128];
+ plugin_t *plugin;
+ plugin_constructor_t constructor;
+
+ if (snprintf(create, sizeof(create), "%s_plugin_create",
+ name) >= sizeof(create))
+ {
+ return NULL;
+ }
+ translate(create, "-", "_");
+ constructor = dlsym(RTLD_DEFAULT, create);
+ if (constructor == NULL)
+ {
+ DBG1(DBG_LIB, "plugin '%s': failed to load - %s not found", name,
+ create);
+ return NULL;
+ }
+ plugin = constructor();
+ if (plugin == NULL)
+ {
+ DBG1(DBG_LIB, "plugin '%s': failed to load - %s returned NULL", name,
+ create);
+ return NULL;
+ }
+ DBG2(DBG_LIB, "plugin '%s': loaded successfully", name);
+
+ return plugin;
+}
+#else
/**
* load a single plugin
*/
static plugin_t* load_plugin(private_plugin_loader_t *this,
char *path, char *name)
{
+ char create[128];
char file[PATH_MAX];
void *handle;
plugin_t *plugin;
plugin_constructor_t constructor;
- snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, name);
-
+ if (snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path,
+ name) >= sizeof(file) ||
+ snprintf(create, sizeof(create), "%s_plugin_create",
+ name) >= sizeof(create))
+ {
+ return NULL;
+ }
+ translate(create, "-", "_");
if (lib->integrity)
{
if (!lib->integrity->check_file(lib->integrity, name, file))
{
- DBG1("plugin '%s': failed file integrity test of '%s'", name, file);
+ DBG1(DBG_LIB, "plugin '%s': failed file integrity test of '%s'",
+ name, file);
return NULL;
}
}
handle = dlopen(file, RTLD_LAZY);
if (handle == NULL)
{
- DBG1("plugin '%s': failed to load '%s' - %s", name, file, dlerror());
+ DBG1(DBG_LIB, "plugin '%s': failed to load '%s' - %s", name, file,
+ dlerror());
return NULL;
}
- constructor = dlsym(handle, "plugin_create");
+ constructor = dlsym(handle, create);
if (constructor == NULL)
{
- DBG1("plugin '%s': failed to load - no plugin_create() function", name);
+ DBG1(DBG_LIB, "plugin '%s': failed to load - %s not found", name,
+ create);
dlclose(handle);
return NULL;
}
@@ -87,25 +134,28 @@ static plugin_t* load_plugin(private_plugin_loader_t *this,
{
if (!lib->integrity->check_segment(lib->integrity, name, constructor))
{
- DBG1("plugin '%s': failed segment integrity test", name);
+ DBG1(DBG_LIB, "plugin '%s': failed segment integrity test", name);
dlclose(handle);
return NULL;
}
- DBG1("plugin '%s': passed file and segment integrity tests", name);
+ DBG1(DBG_LIB, "plugin '%s': passed file and segment integrity tests",
+ name);
}
plugin = constructor();
if (plugin == NULL)
{
- DBG1("plugin '%s': failed to load - plugin_create() returned NULL", name);
+ DBG1(DBG_LIB, "plugin '%s': failed to load - %s returned NULL", name,
+ create);
dlclose(handle);
return NULL;
}
- DBG2("plugin '%s': loaded successfully", name);
+ DBG2(DBG_LIB, "plugin '%s': loaded successfully", name);
/* we do not store or free dlopen() handles, leak_detective requires
* the modules to keep loaded until leak report */
return plugin;
}
+#endif
/**
* Implementation of plugin_loader_t.load_plugins.
@@ -116,10 +166,12 @@ static bool load(private_plugin_loader_t *this, char *path, char *list)
char *token;
bool critical_failed = FALSE;
+#ifndef MONOLITHIC
if (path == NULL)
{
path = PLUGINDIR;
}
+#endif
enumerator = enumerator_create_token(list, " ", " ");
while (!critical_failed && enumerator->enumerate(enumerator, &token))
@@ -147,7 +199,7 @@ static bool load(private_plugin_loader_t *this, char *path, char *list)
if (critical)
{
critical_failed = TRUE;
- DBG1("loading critical plugin '%s' failed", token);
+ DBG1(DBG_LIB, "loading critical plugin '%s' failed", token);
}
free(token);
}
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.am b/src/libstrongswan/plugins/pubkey/Makefile.am
index 770d77325..c2974a585 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.am
+++ b/src/libstrongswan/plugins/pubkey/Makefile.am
@@ -3,10 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-pubkey.la
+else
plugin_LTLIBRARIES = libstrongswan-pubkey.la
+endif
-libstrongswan_pubkey_la_SOURCES = pubkey_plugin.h pubkey_plugin.c \
- pubkey_cert.h pubkey_cert.c
+libstrongswan_pubkey_la_SOURCES = \
+ pubkey_plugin.h pubkey_plugin.c \
+ pubkey_cert.h pubkey_cert.c
libstrongswan_pubkey_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in
index f95e7b357..5fe3d58f1 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.in
+++ b/src/libstrongswan/plugins/pubkey/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_pubkey_la_LIBADD =
am_libstrongswan_pubkey_la_OBJECTS = pubkey_plugin.lo pubkey_cert.lo
libstrongswan_pubkey_la_OBJECTS = \
@@ -80,6 +80,9 @@ libstrongswan_pubkey_la_OBJECTS = \
libstrongswan_pubkey_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_pubkey_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_pubkey_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_pubkey_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,9 +258,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-pubkey.la
-libstrongswan_pubkey_la_SOURCES = pubkey_plugin.h pubkey_plugin.c \
- pubkey_cert.h pubkey_cert.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-pubkey.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-pubkey.la
+libstrongswan_pubkey_la_SOURCES = \
+ pubkey_plugin.h pubkey_plugin.c \
+ pubkey_cert.h pubkey_cert.c
libstrongswan_pubkey_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -293,6 +299,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -325,7 +340,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-pubkey.la: $(libstrongswan_pubkey_la_OBJECTS) $(libstrongswan_pubkey_la_DEPENDENCIES)
- $(libstrongswan_pubkey_la_LINK) -rpath $(plugindir) $(libstrongswan_pubkey_la_OBJECTS) $(libstrongswan_pubkey_la_LIBADD) $(LIBS)
+ $(libstrongswan_pubkey_la_LINK) $(am_libstrongswan_pubkey_la_rpath) $(libstrongswan_pubkey_la_OBJECTS) $(libstrongswan_pubkey_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -479,8 +494,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -551,18 +566,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
index ad84eed99..b0eabc9ee 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_pubkey_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *pubkey_plugin_create()
{
private_pubkey_plugin_t *this = malloc_thing(private_pubkey_plugin_t);
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_plugin.h b/src/libstrongswan/plugins/pubkey/pubkey_plugin.h
index a3fd2f155..db71bddc0 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_plugin.h
+++ b/src/libstrongswan/plugins/pubkey/pubkey_plugin.h
@@ -39,9 +39,4 @@ struct pubkey_plugin_t {
plugin_t plugin;
};
-/**
- * Create a pubkey_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** PUBKEY_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/random/Makefile.am b/src/libstrongswan/plugins/random/Makefile.am
index 7c2283ae7..5df992718 100644
--- a/src/libstrongswan/plugins/random/Makefile.am
+++ b/src/libstrongswan/plugins/random/Makefile.am
@@ -5,9 +5,14 @@ AM_CFLAGS = -rdynamic \
-DDEV_RANDOM=\"${random_device}\" \
-DDEV_URANDOM=\"${urandom_device}\"
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-random.la
+else
plugin_LTLIBRARIES = libstrongswan-random.la
+endif
-libstrongswan_random_la_SOURCES = random_plugin.h random_plugin.c \
- random_rng.c random_rng.h
-libstrongswan_random_la_LDFLAGS = -module -avoid-version
+libstrongswan_random_la_SOURCES = \
+ random_plugin.h random_plugin.c \
+ random_rng.c random_rng.h
+libstrongswan_random_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in
index 355ab14bc..27360aa8c 100644
--- a/src/libstrongswan/plugins/random/Makefile.in
+++ b/src/libstrongswan/plugins/random/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_random_la_LIBADD =
am_libstrongswan_random_la_OBJECTS = random_plugin.lo random_rng.lo
libstrongswan_random_la_OBJECTS = \
@@ -80,6 +80,9 @@ libstrongswan_random_la_OBJECTS = \
libstrongswan_random_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_random_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_random_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_random_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -257,9 +261,11 @@ AM_CFLAGS = -rdynamic \
-DDEV_RANDOM=\"${random_device}\" \
-DDEV_URANDOM=\"${urandom_device}\"
-plugin_LTLIBRARIES = libstrongswan-random.la
-libstrongswan_random_la_SOURCES = random_plugin.h random_plugin.c \
- random_rng.c random_rng.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-random.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-random.la
+libstrongswan_random_la_SOURCES = \
+ random_plugin.h random_plugin.c \
+ random_rng.c random_rng.h
libstrongswan_random_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -296,6 +302,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -328,7 +343,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-random.la: $(libstrongswan_random_la_OBJECTS) $(libstrongswan_random_la_DEPENDENCIES)
- $(libstrongswan_random_la_LINK) -rpath $(plugindir) $(libstrongswan_random_la_OBJECTS) $(libstrongswan_random_la_LIBADD) $(LIBS)
+ $(libstrongswan_random_la_LINK) $(am_libstrongswan_random_la_rpath) $(libstrongswan_random_la_OBJECTS) $(libstrongswan_random_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -482,8 +497,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -554,18 +569,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c
index df0a8f556..39678ba71 100644
--- a/src/libstrongswan/plugins/random/random_plugin.c
+++ b/src/libstrongswan/plugins/random/random_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_random_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *random_plugin_create()
{
private_random_plugin_t *this = malloc_thing(private_random_plugin_t);
diff --git a/src/libstrongswan/plugins/random/random_plugin.h b/src/libstrongswan/plugins/random/random_plugin.h
index 6ce0f71be..7e22c3e5f 100644
--- a/src/libstrongswan/plugins/random/random_plugin.h
+++ b/src/libstrongswan/plugins/random/random_plugin.h
@@ -39,9 +39,4 @@ struct random_plugin_t {
plugin_t plugin;
};
-/**
- * Create a random_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** RANDOM_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/random/random_rng.c b/src/libstrongswan/plugins/random/random_rng.c
index 34f300296..b09f3f57a 100644
--- a/src/libstrongswan/plugins/random/random_rng.c
+++ b/src/libstrongswan/plugins/random/random_rng.c
@@ -71,7 +71,7 @@ static void get_bytes(private_random_rng_t *this, size_t bytes,
got = read(this->dev, buffer + done, bytes - done);
if (got <= 0)
{
- DBG1("reading from \"%s\" failed: %s, retrying...",
+ DBG1(DBG_LIB, "reading from \"%s\" failed: %s, retrying...",
this->file, strerror(errno));
close(this->dev);
sleep(1);
@@ -124,7 +124,7 @@ random_rng_t *random_rng_create(rng_quality_t quality)
this->dev = open(this->file, 0);
if (this->dev < 0)
{
- DBG1("opening \"%s\" failed: %s", this->file, strerror(errno));
+ DBG1(DBG_LIB, "opening \"%s\" failed: %s", this->file, strerror(errno));
free(this);
return NULL;
}
diff --git a/src/libstrongswan/plugins/sha1/Makefile.am b/src/libstrongswan/plugins/sha1/Makefile.am
index ead51a45a..4e539fd83 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.am
+++ b/src/libstrongswan/plugins/sha1/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-sha1.la
+else
plugin_LTLIBRARIES = libstrongswan-sha1.la
+endif
-libstrongswan_sha1_la_SOURCES = sha1_plugin.h sha1_plugin.c \
+libstrongswan_sha1_la_SOURCES = \
+ sha1_plugin.h sha1_plugin.c \
sha1_hasher.c sha1_hasher.h sha1_prf.c sha1_prf.h
-libstrongswan_sha1_la_LDFLAGS = -module -avoid-version
+libstrongswan_sha1_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in
index 4f08b882c..dacb5be4b 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.in
+++ b/src/libstrongswan/plugins/sha1/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_sha1_la_LIBADD =
am_libstrongswan_sha1_la_OBJECTS = sha1_plugin.lo sha1_hasher.lo \
sha1_prf.lo
@@ -80,6 +80,8 @@ libstrongswan_sha1_la_OBJECTS = $(am_libstrongswan_sha1_la_OBJECTS)
libstrongswan_sha1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_sha1_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_sha1_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_sha1_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,8 +257,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-sha1.la
-libstrongswan_sha1_la_SOURCES = sha1_plugin.h sha1_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-sha1.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-sha1.la
+libstrongswan_sha1_la_SOURCES = \
+ sha1_plugin.h sha1_plugin.c \
sha1_hasher.c sha1_hasher.h sha1_prf.c sha1_prf.h
libstrongswan_sha1_la_LDFLAGS = -module -avoid-version
@@ -293,6 +298,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -325,7 +339,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-sha1.la: $(libstrongswan_sha1_la_OBJECTS) $(libstrongswan_sha1_la_DEPENDENCIES)
- $(libstrongswan_sha1_la_LINK) -rpath $(plugindir) $(libstrongswan_sha1_la_OBJECTS) $(libstrongswan_sha1_la_LIBADD) $(LIBS)
+ $(libstrongswan_sha1_la_LINK) $(am_libstrongswan_sha1_la_rpath) $(libstrongswan_sha1_la_OBJECTS) $(libstrongswan_sha1_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -480,8 +494,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -552,18 +566,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/sha1/sha1_plugin.c b/src/libstrongswan/plugins/sha1/sha1_plugin.c
index a038228da..7b9cf878f 100644
--- a/src/libstrongswan/plugins/sha1/sha1_plugin.c
+++ b/src/libstrongswan/plugins/sha1/sha1_plugin.c
@@ -47,7 +47,7 @@ static void destroy(private_sha1_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *sha1_plugin_create()
{
private_sha1_plugin_t *this = malloc_thing(private_sha1_plugin_t);
diff --git a/src/libstrongswan/plugins/sha1/sha1_plugin.h b/src/libstrongswan/plugins/sha1/sha1_plugin.h
index 36b12b91e..cd1ff615d 100644
--- a/src/libstrongswan/plugins/sha1/sha1_plugin.h
+++ b/src/libstrongswan/plugins/sha1/sha1_plugin.h
@@ -39,9 +39,4 @@ struct sha1_plugin_t {
plugin_t plugin;
};
-/**
- * Create a sha1_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** SHA1_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/sha2/Makefile.am b/src/libstrongswan/plugins/sha2/Makefile.am
index 5422e1d4e..a255d0609 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.am
+++ b/src/libstrongswan/plugins/sha2/Makefile.am
@@ -3,8 +3,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-sha2.la
+else
plugin_LTLIBRARIES = libstrongswan-sha2.la
+endif
-libstrongswan_sha2_la_SOURCES = sha2_plugin.h sha2_plugin.c sha2_hasher.c sha2_hasher.h
-libstrongswan_sha2_la_LDFLAGS = -module -avoid-version
+libstrongswan_sha2_la_SOURCES = \
+ sha2_plugin.h sha2_plugin.c sha2_hasher.c sha2_hasher.h
+libstrongswan_sha2_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in
index e4ea58094..6db4374c8 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.in
+++ b/src/libstrongswan/plugins/sha2/Makefile.in
@@ -72,13 +72,15 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_sha2_la_LIBADD =
am_libstrongswan_sha2_la_OBJECTS = sha2_plugin.lo sha2_hasher.lo
libstrongswan_sha2_la_OBJECTS = $(am_libstrongswan_sha2_la_OBJECTS)
libstrongswan_sha2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_sha2_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_sha2_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_sha2_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -217,6 +219,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -253,8 +256,11 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-sha2.la
-libstrongswan_sha2_la_SOURCES = sha2_plugin.h sha2_plugin.c sha2_hasher.c sha2_hasher.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-sha2.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-sha2.la
+libstrongswan_sha2_la_SOURCES = \
+ sha2_plugin.h sha2_plugin.c sha2_hasher.c sha2_hasher.h
+
libstrongswan_sha2_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -290,6 +296,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -322,7 +337,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-sha2.la: $(libstrongswan_sha2_la_OBJECTS) $(libstrongswan_sha2_la_DEPENDENCIES)
- $(libstrongswan_sha2_la_LINK) -rpath $(plugindir) $(libstrongswan_sha2_la_OBJECTS) $(libstrongswan_sha2_la_LIBADD) $(LIBS)
+ $(libstrongswan_sha2_la_LINK) $(am_libstrongswan_sha2_la_rpath) $(libstrongswan_sha2_la_OBJECTS) $(libstrongswan_sha2_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -476,8 +491,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -548,18 +563,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/sha2/sha2_plugin.c b/src/libstrongswan/plugins/sha2/sha2_plugin.c
index 90f7cec77..810d9922a 100644
--- a/src/libstrongswan/plugins/sha2/sha2_plugin.c
+++ b/src/libstrongswan/plugins/sha2/sha2_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_sha2_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *sha2_plugin_create()
{
private_sha2_plugin_t *this = malloc_thing(private_sha2_plugin_t);
diff --git a/src/libstrongswan/plugins/sha2/sha2_plugin.h b/src/libstrongswan/plugins/sha2/sha2_plugin.h
index b80f7560e..48ee2d94c 100644
--- a/src/libstrongswan/plugins/sha2/sha2_plugin.h
+++ b/src/libstrongswan/plugins/sha2/sha2_plugin.h
@@ -39,9 +39,4 @@ struct sha2_plugin_t {
plugin_t plugin;
};
-/**
- * Create a sha2_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** SHA2_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.am b/src/libstrongswan/plugins/sqlite/Makefile.am
index f26e31294..2e1d9733f 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.am
+++ b/src/libstrongswan/plugins/sqlite/Makefile.am
@@ -3,10 +3,16 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-sqlite.la
+else
plugin_LTLIBRARIES = libstrongswan-sqlite.la
+endif
-libstrongswan_sqlite_la_SOURCES = sqlite_plugin.h sqlite_plugin.c \
+libstrongswan_sqlite_la_SOURCES = \
+ sqlite_plugin.h sqlite_plugin.c \
sqlite_database.h sqlite_database.c
+
libstrongswan_sqlite_la_LDFLAGS = -module -avoid-version
-libstrongswan_sqlite_la_LIBADD = -lsqlite3
+libstrongswan_sqlite_la_LIBADD = -lsqlite3
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in
index 831408c9e..cb466ad03 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.in
+++ b/src/libstrongswan/plugins/sqlite/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_sqlite_la_DEPENDENCIES =
am_libstrongswan_sqlite_la_OBJECTS = sqlite_plugin.lo \
sqlite_database.lo
@@ -81,6 +81,9 @@ libstrongswan_sqlite_la_OBJECTS = \
libstrongswan_sqlite_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_sqlite_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_sqlite_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_sqlite_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -219,6 +222,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -255,8 +259,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-sqlite.la
-libstrongswan_sqlite_la_SOURCES = sqlite_plugin.h sqlite_plugin.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-sqlite.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-sqlite.la
+libstrongswan_sqlite_la_SOURCES = \
+ sqlite_plugin.h sqlite_plugin.c \
sqlite_database.h sqlite_database.c
libstrongswan_sqlite_la_LDFLAGS = -module -avoid-version
@@ -295,6 +301,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -327,7 +342,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-sqlite.la: $(libstrongswan_sqlite_la_OBJECTS) $(libstrongswan_sqlite_la_DEPENDENCIES)
- $(libstrongswan_sqlite_la_LINK) -rpath $(plugindir) $(libstrongswan_sqlite_la_OBJECTS) $(libstrongswan_sqlite_la_LIBADD) $(LIBS)
+ $(libstrongswan_sqlite_la_LINK) $(am_libstrongswan_sqlite_la_rpath) $(libstrongswan_sqlite_la_OBJECTS) $(libstrongswan_sqlite_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -481,8 +496,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -553,18 +568,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c
index 721f1a126..3e20dbb51 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_database.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c
@@ -110,11 +110,13 @@ static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
}
else
{
- DBG1("preparing sqlite statement failed: %s", sqlite3_errmsg(this->db));
+ DBG1(DBG_LIB, "preparing sqlite statement failed: %s",
+ sqlite3_errmsg(this->db));
}
if (res != SQLITE_OK)
{
- DBG1("binding sqlite statement failed: %s", sqlite3_errmsg(this->db));
+ DBG1(DBG_LIB, "binding sqlite statement failed: %s",
+ sqlite3_errmsg(this->db));
sqlite3_finalize(stmt);
return NULL;
}
@@ -160,7 +162,7 @@ static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
case SQLITE_ROW:
break;
default:
- DBG1("stepping sqlite statement failed: %s",
+ DBG1(DBG_LIB, "stepping sqlite statement failed: %s",
sqlite3_errmsg(this->database->db));
/* fall */
case SQLITE_DONE:
@@ -203,7 +205,7 @@ static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
break;
}
default:
- DBG1("invalid result type supplied");
+ DBG1(DBG_LIB, "invalid result type supplied");
return FALSE;
}
}
@@ -272,7 +274,8 @@ static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...)
}
else
{
- DBG1("sqlite execute failed: %s", sqlite3_errmsg(this->db));
+ DBG1(DBG_LIB, "sqlite execute failed: %s",
+ sqlite3_errmsg(this->db));
}
sqlite3_finalize(stmt);
}
@@ -337,7 +340,7 @@ sqlite_database_t *sqlite_database_create(char *uri)
if (sqlite3_open(file, &this->db) != SQLITE_OK)
{
- DBG1("opening SQLite database '%s' failed: %s",
+ DBG1(DBG_LIB, "opening SQLite database '%s' failed: %s",
file, sqlite3_errmsg(this->db));
destroy(this);
return NULL;
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
index 955402bf9..332d82318 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
@@ -44,7 +44,7 @@ static void destroy(private_sqlite_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *sqlite_plugin_create()
{
private_sqlite_plugin_t *this = malloc_thing(private_sqlite_plugin_t);
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_plugin.h b/src/libstrongswan/plugins/sqlite/sqlite_plugin.h
index 82735a311..dbc461cf4 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_plugin.h
+++ b/src/libstrongswan/plugins/sqlite/sqlite_plugin.h
@@ -39,9 +39,4 @@ struct sqlite_plugin_t {
plugin_t plugin;
};
-/**
- * Create a sqlite_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** SQLITE_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am
index 6028805c4..6d3b05d19 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.am
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.am
@@ -3,7 +3,11 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-test-vectors.la
+else
plugin_LTLIBRARIES = libstrongswan-test-vectors.la
+endif
libstrongswan_test_vectors_la_SOURCES = \
test_vectors_plugin.h test_vectors_plugin.c test_vectors.h \
@@ -29,5 +33,5 @@ libstrongswan_test_vectors_la_SOURCES = \
test_vectors/sha2_hmac.c \
test_vectors/fips_prf.c \
test_vectors/rng.c
-libstrongswan_test_vectors_la_LDFLAGS = -module -avoid-version
+libstrongswan_test_vectors_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index a8674d282..dbe62c056 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_test_vectors_la_LIBADD =
am_libstrongswan_test_vectors_la_OBJECTS = test_vectors_plugin.lo \
3des_cbc.lo aes_cbc.lo aes_xcbc.lo blowfish.lo camellia_cbc.lo \
@@ -85,6 +85,9 @@ libstrongswan_test_vectors_la_LINK = $(LIBTOOL) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_test_vectors_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_test_vectors_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_test_vectors_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -223,6 +226,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -259,7 +263,8 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-test-vectors.la
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-test-vectors.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-test-vectors.la
libstrongswan_test_vectors_la_SOURCES = \
test_vectors_plugin.h test_vectors_plugin.c test_vectors.h \
test_vectors/3des_cbc.c \
@@ -320,6 +325,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -352,7 +366,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-test-vectors.la: $(libstrongswan_test_vectors_la_OBJECTS) $(libstrongswan_test_vectors_la_DEPENDENCIES)
- $(libstrongswan_test_vectors_la_LINK) -rpath $(plugindir) $(libstrongswan_test_vectors_la_OBJECTS) $(libstrongswan_test_vectors_la_LIBADD) $(LIBS)
+ $(libstrongswan_test_vectors_la_LINK) $(am_libstrongswan_test_vectors_la_rpath) $(libstrongswan_test_vectors_la_OBJECTS) $(libstrongswan_test_vectors_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -681,8 +695,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -753,18 +767,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/rng.c b/src/libstrongswan/plugins/test_vectors/test_vectors/rng.c
index 4dc1cc174..18e0c9278 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors/rng.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/rng.c
@@ -44,7 +44,7 @@ static bool test_monobit(monobit_t *param, chunk_t data)
}
}
}
- DBG2(" Monobit: %d/%d bits set", bits, data.len * 8);
+ DBG2(DBG_LIB, " Monobit: %d/%d bits set", bits, data.len * 8);
if (bits > param->lower && bits < param->upper)
{
return TRUE;
@@ -101,7 +101,7 @@ static bool test_poker(poker_t *param, chunk_t data)
sum += (counter[i] * counter[i]) / 5000.0 * 16.0;
}
sum -= 5000.0;
- DBG2(" Poker: %f", sum);
+ DBG2(DBG_LIB, " Poker: %f", sum);
if (sum > param->lower && sum < param->upper)
{
return TRUE;
@@ -190,7 +190,7 @@ static bool test_runs(runs_t *param, chunk_t data)
}
}
- DBG2(" Runs: zero: %d/%d/%d/%d/%d/%d, one: %d/%d/%d/%d/%d/%d, "
+ DBG2(DBG_LIB, " Runs: zero: %d/%d/%d/%d/%d/%d, one: %d/%d/%d/%d/%d/%d, "
"longruns: %d",
zero_runs[1], zero_runs[2], zero_runs[3],
zero_runs[4], zero_runs[5], zero_runs[6],
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
index 7ad8c3c73..234d237f3 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
@@ -104,7 +104,7 @@ static void destroy(private_test_vectors_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *test_vectors_plugin_create()
{
private_test_vectors_plugin_t *this = malloc_thing(private_test_vectors_plugin_t);
int i;
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.h b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.h
index 9cb959c88..661529295 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.h
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.h
@@ -39,9 +39,4 @@ struct test_vectors_plugin_t {
plugin_t plugin;
};
-/**
- * Create a test_vectors_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** TEST_VECTORS_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/x509/Makefile.am b/src/libstrongswan/plugins/x509/Makefile.am
index 853b1cebc..4b50d78dc 100644
--- a/src/libstrongswan/plugins/x509/Makefile.am
+++ b/src/libstrongswan/plugins/x509/Makefile.am
@@ -3,14 +3,19 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-x509.la
+else
plugin_LTLIBRARIES = libstrongswan-x509.la
+endif
-libstrongswan_x509_la_SOURCES = x509_plugin.h x509_plugin.c \
- x509_cert.h x509_cert.c \
- x509_crl.h x509_crl.c \
- x509_ac.h x509_ac.c \
- x509_pkcs10.h x509_pkcs10.c \
- x509_ocsp_request.h x509_ocsp_request.c \
- x509_ocsp_response.h x509_ocsp_response.c
-libstrongswan_x509_la_LDFLAGS = -module -avoid-version
+libstrongswan_x509_la_SOURCES = \
+ x509_plugin.h x509_plugin.c \
+ x509_cert.h x509_cert.c \
+ x509_crl.h x509_crl.c \
+ x509_ac.h x509_ac.c \
+ x509_pkcs10.h x509_pkcs10.c \
+ x509_ocsp_request.h x509_ocsp_request.c \
+ x509_ocsp_response.h x509_ocsp_response.c
+libstrongswan_x509_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in
index 428643254..2bee453cd 100644
--- a/src/libstrongswan/plugins/x509/Makefile.in
+++ b/src/libstrongswan/plugins/x509/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_x509_la_LIBADD =
am_libstrongswan_x509_la_OBJECTS = x509_plugin.lo x509_cert.lo \
x509_crl.lo x509_ac.lo x509_pkcs10.lo x509_ocsp_request.lo \
@@ -81,6 +81,8 @@ libstrongswan_x509_la_OBJECTS = $(am_libstrongswan_x509_la_OBJECTS)
libstrongswan_x509_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_x509_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_x509_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_x509_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -219,6 +221,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -255,14 +258,16 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-x509.la
-libstrongswan_x509_la_SOURCES = x509_plugin.h x509_plugin.c \
- x509_cert.h x509_cert.c \
- x509_crl.h x509_crl.c \
- x509_ac.h x509_ac.c \
- x509_pkcs10.h x509_pkcs10.c \
- x509_ocsp_request.h x509_ocsp_request.c \
- x509_ocsp_response.h x509_ocsp_response.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-x509.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-x509.la
+libstrongswan_x509_la_SOURCES = \
+ x509_plugin.h x509_plugin.c \
+ x509_cert.h x509_cert.c \
+ x509_crl.h x509_crl.c \
+ x509_ac.h x509_ac.c \
+ x509_pkcs10.h x509_pkcs10.c \
+ x509_ocsp_request.h x509_ocsp_request.c \
+ x509_ocsp_response.h x509_ocsp_response.c
libstrongswan_x509_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -299,6 +304,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -331,7 +345,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-x509.la: $(libstrongswan_x509_la_OBJECTS) $(libstrongswan_x509_la_DEPENDENCIES)
- $(libstrongswan_x509_la_LINK) -rpath $(plugindir) $(libstrongswan_x509_la_OBJECTS) $(libstrongswan_x509_la_LIBADD) $(LIBS)
+ $(libstrongswan_x509_la_LINK) $(am_libstrongswan_x509_la_rpath) $(libstrongswan_x509_la_OBJECTS) $(libstrongswan_x509_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -490,8 +504,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -562,18 +576,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index 79ff80933..95e72789e 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -192,7 +192,7 @@ static bool parse_directoryName(chunk_t blob, int level, bool implicit, identifi
}
else
{
- DBG1("more than one directory name - first selected");
+ DBG1(DBG_LIB, "more than one directory name - first selected");
directoryName->destroy(directoryName);
}
}
@@ -200,7 +200,7 @@ static bool parse_directoryName(chunk_t blob, int level, bool implicit, identifi
}
else
{
- DBG1("no directoryName found");
+ DBG1(DBG_LIB, "no directoryName found");
}
list->destroy(list);
@@ -359,10 +359,11 @@ static bool parse_certificate(private_x509_ac_t *this)
break;
case AC_OBJ_VERSION:
this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
- DBG2(" v%d", this->version);
+ DBG2(DBG_LIB, " v%d", this->version);
if (this->version != 2)
{
- DBG1("v%d attribute certificates are not supported", this->version);
+ DBG1(DBG_LIB, "v%d attribute certificates are not "
+ "supported", this->version);
goto end;
}
break;
@@ -407,20 +408,20 @@ static bool parse_certificate(private_x509_ac_t *this)
switch (type)
{
case OID_AUTHENTICATION_INFO:
- DBG2(" need to parse authenticationInfo");
+ DBG2(DBG_LIB, " need to parse authenticationInfo");
break;
case OID_ACCESS_IDENTITY:
- DBG2(" need to parse accessIdentity");
+ DBG2(DBG_LIB, " need to parse accessIdentity");
break;
case OID_CHARGING_IDENTITY:
- DBG2("-- > --");
+ DBG2(DBG_LIB, "-- > --");
this->charging = ietf_attributes_create_from_encoding(object);
- DBG2("-- < --");
+ DBG2(DBG_LIB, "-- < --");
break;
case OID_GROUP:
- DBG2("-- > --");
+ DBG2(DBG_LIB, "-- > --");
this->groups = ietf_attributes_create_from_encoding(object);
- DBG2("-- < --");
+ DBG2(DBG_LIB, "-- < --");
break;
case OID_ROLE:
parse_roleSyntax(object, level);
@@ -435,21 +436,21 @@ static bool parse_certificate(private_x509_ac_t *this)
break;
case AC_OBJ_CRITICAL:
critical = object.len && *object.ptr;
- DBG2(" %s",(critical)?"TRUE":"FALSE");
+ DBG2(DBG_LIB, " %s",(critical)?"TRUE":"FALSE");
break;
case AC_OBJ_EXTN_VALUE:
{
switch (extn_oid)
{
case OID_CRL_DISTRIBUTION_POINTS:
- DBG2(" need to parse crlDistributionPoints");
+ DBG2(DBG_LIB, " need to parse crlDistributionPoints");
break;
case OID_AUTHORITY_KEY_ID:
this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
level, &this->authKeySerialNumber);
break;
case OID_TARGET_INFORMATION:
- DBG2(" need to parse targetInformation");
+ DBG2(DBG_LIB, " need to parse targetInformation");
break;
case OID_NO_REV_AVAIL:
this->noRevAvail = TRUE;
@@ -464,7 +465,7 @@ static bool parse_certificate(private_x509_ac_t *this)
NULL);
if (this->algorithm != sig_alg)
{
- DBG1(" signature algorithms do not agree");
+ DBG1(DBG_LIB, " signature algorithms do not agree");
success = FALSE;
goto end;
}
@@ -824,9 +825,9 @@ static bool is_newer(private_x509_ac_t *this, ac_t *that)
this_cert->get_validity(this_cert, &now, &this_update, NULL);
that_cert->get_validity(that_cert, &now, &that_update, NULL);
new = this_update > that_update;
- DBG1(" attr cert from %T is %s - existing attr cert from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
+ DBG1(DBG_LIB, " attr cert from %T is %s - existing attr cert from %T %s",
+ &this_update, FALSE, new ? "newer":"not newer",
+ &that_update, FALSE, new ? "replaced":"retained");
return new;
}
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 3b729236e..bdbaa8d4a 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -219,7 +219,7 @@ static void parse_basicConstraints(chunk_t blob, int level0,
{
case BASIC_CONSTRAINTS_CA:
isCA = object.len && *object.ptr;
- DBG2(" %s", isCA ? "TRUE" : "FALSE");
+ DBG2(DBG_LIB, " %s", isCA ? "TRUE" : "FALSE");
if (isCA)
{
this->flags |= X509_CA;
@@ -383,7 +383,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
if (id_type != ID_ANY)
{
gn = identification_create_from_encoding(id_type, object);
- DBG2(" '%Y'", gn);
+ DBG2(DBG_LIB, " '%Y'", gn);
goto end;
}
}
@@ -539,7 +539,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0,
/* parsing went wrong - abort */
goto end;
}
- DBG2(" '%Y'", id);
+ DBG2(DBG_LIB, " '%Y'", id);
if (accessMethod == OID_OCSP &&
asprintf(&uri, "%Y", id) > 0)
{
@@ -704,34 +704,36 @@ static bool check_address_object(ts_type_t ts_type, chunk_t object)
case TS_IPV4_ADDR_RANGE:
if (object.len > 5)
{
- DBG1("IPv4 address object is larger than 5 octets");
+ DBG1(DBG_LIB, "IPv4 address object is larger than 5 octets");
return FALSE;
}
break;
case TS_IPV6_ADDR_RANGE:
if (object.len > 17)
{
- DBG1("IPv6 address object is larger than 17 octets");
+ DBG1(DBG_LIB, "IPv6 address object is larger than 17 octets");
return FALSE;
}
break;
default:
- DBG1("unknown address family");
+ DBG1(DBG_LIB, "unknown address family");
return FALSE;
}
if (object.len == 0)
{
- DBG1("An ASN.1 bit string must contain at least the initial octet");
+ DBG1(DBG_LIB, "An ASN.1 bit string must contain at least the "
+ "initial octet");
return FALSE;
}
if (object.len == 1 && object.ptr[0] != 0)
{
- DBG1("An empty ASN.1 bit string must contain a zero initial octet");
+ DBG1(DBG_LIB, "An empty ASN.1 bit string must contain a zero "
+ "initial octet");
return FALSE;
}
if (object.ptr[0] > 7)
{
- DBG1("number of unused bits is too large");
+ DBG1(DBG_LIB, "number of unused bits is too large");
return FALSE;
}
return TRUE;
@@ -769,11 +771,11 @@ static void parse_ipAddrBlocks(chunk_t blob, int level0,
{
break;
}
- DBG2(" %N", ts_type_name, ts_type);
+ DBG2(DBG_LIB, " %N", ts_type_name, ts_type);
}
break;
case IP_ADDR_BLOCKS_INHERIT:
- DBG1("inherit choice is not supported");
+ DBG1(DBG_LIB, "inherit choice is not supported");
break;
case IP_ADDR_BLOCKS_PREFIX:
if (!check_address_object(ts_type, object))
@@ -782,7 +784,7 @@ static void parse_ipAddrBlocks(chunk_t blob, int level0,
}
ts = traffic_selector_create_from_rfc3779_format(ts_type,
object, object);
- DBG2(" %R", ts);
+ DBG2(DBG_LIB, " %R", ts);
this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
break;
case IP_ADDR_BLOCKS_MIN:
@@ -799,7 +801,7 @@ static void parse_ipAddrBlocks(chunk_t blob, int level0,
}
ts = traffic_selector_create_from_rfc3779_format(ts_type,
min_object, object);
- DBG2(" %R", ts);
+ DBG2(DBG_LIB, " %R", ts);
this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
break;
default:
@@ -893,12 +895,12 @@ static bool parse_certificate(private_x509_cert_t *this)
this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
if (this->version < 1 || this->version > 3)
{
- DBG1("X.509v%d not supported", this->version);
+ DBG1(DBG_LIB, "X.509v%d not supported", this->version);
goto end;
}
else
{
- DBG2(" X.509v%d", this->version);
+ DBG2(DBG_LIB, " X.509v%d", this->version);
}
break;
case X509_OBJ_SERIAL_NUMBER:
@@ -909,7 +911,7 @@ static bool parse_certificate(private_x509_cert_t *this)
break;
case X509_OBJ_ISSUER:
this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
- DBG2(" '%Y'", this->issuer);
+ DBG2(DBG_LIB, " '%Y'", this->issuer);
break;
case X509_OBJ_NOT_BEFORE:
this->notBefore = asn1_parse_time(object, level);
@@ -919,13 +921,13 @@ static bool parse_certificate(private_x509_cert_t *this)
break;
case X509_OBJ_SUBJECT:
this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
- DBG2(" '%Y'", this->subject);
+ DBG2(DBG_LIB, " '%Y'", this->subject);
break;
case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO:
- DBG2("-- > --");
+ DBG2(DBG_LIB, "-- > --");
this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
- DBG2("-- < --");
+ DBG2(DBG_LIB, "-- < --");
if (this->public_key == NULL)
{
goto end;
@@ -934,7 +936,7 @@ static bool parse_certificate(private_x509_cert_t *this)
case X509_OBJ_OPTIONAL_EXTENSIONS:
if (this->version != 3)
{
- DBG1("Only X.509v3 certificates have extensions");
+ DBG1(DBG_LIB, "Only X.509v3 certificates have extensions");
goto end;
}
break;
@@ -943,7 +945,7 @@ static bool parse_certificate(private_x509_cert_t *this)
break;
case X509_OBJ_CRITICAL:
critical = object.len && *object.ptr;
- DBG2(" %s", critical ? "TRUE" : "FALSE");
+ DBG2(DBG_LIB, " %s", critical ? "TRUE" : "FALSE");
break;
case X509_OBJ_EXTN_VALUE:
{
@@ -974,6 +976,9 @@ static bool parse_certificate(private_x509_cert_t *this)
case OID_AUTHORITY_INFO_ACCESS:
parse_authorityInfoAccess(object, level, this);
break;
+ case OID_KEY_USAGE:
+ /* TODO parse the flags */
+ break;
case OID_EXTENDED_KEY_USAGE:
parse_extendedKeyUsage(object, level, this);
break;
@@ -994,7 +999,7 @@ static bool parse_certificate(private_x509_cert_t *this)
if (critical && lib->settings->get_bool(lib->settings,
"libstrongswan.plugins.x509.enforce_critical", FALSE))
{
- DBG1("critical %s extension not supported",
+ DBG1(DBG_LIB, "critical %s extension not supported",
(extn_oid == OID_UNKNOWN) ? "unknown" :
(char*)oid_names[extn_oid].name);
goto end;
@@ -1007,7 +1012,7 @@ static bool parse_certificate(private_x509_cert_t *this)
this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
if (this->algorithm != sig_alg)
{
- DBG1(" signature algorithms do not agree");
+ DBG1(DBG_LIB, " signature algorithms do not agree");
goto end;
}
break;
@@ -1035,7 +1040,7 @@ end:
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (hasher == NULL)
{
- DBG1(" unable to create hash of certificate, SHA1 not supported");
+ DBG1(DBG_LIB, " unable to create hash of certificate, SHA1 not supported");
return NULL;
}
hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash);
@@ -1214,9 +1219,9 @@ static bool is_newer(certificate_t *this, certificate_t *that)
this->get_validity(this, &now, &this_update, NULL);
that->get_validity(that, &now, &that_update, NULL);
new = this_update > that_update;
- DBG1(" certificate from %T is %s - existing certificate from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
+ DBG1(DBG_LIB, " certificate from %T is %s - existing certificate "
+ "from %T %s", &this_update, FALSE, new ? "newer":"not newer",
+ &that_update, FALSE, new ? "replaced":"retained");
return new;
}
@@ -1453,7 +1458,7 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list)
context = ASN1_CONTEXT_S_7;
break;
default:
- DBG1("encoding %N as subjectAltName not supported",
+ DBG1(DBG_LIB, "encoding %N as subjectAltName not supported",
id_type_names, id->get_type(id));
enumerator->destroy(enumerator);
free(subjectAltNames.ptr);
@@ -1481,7 +1486,9 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
chunk_t extensions = chunk_empty, extendedKeyUsage = chunk_empty;
chunk_t serverAuth = chunk_empty, clientAuth = chunk_empty;
chunk_t ocspSigning = chunk_empty;
- chunk_t basicConstraints = chunk_empty, subjectAltNames = chunk_empty;
+ chunk_t basicConstraints = chunk_empty;
+ chunk_t keyUsage = chunk_empty;
+ chunk_t subjectAltNames = chunk_empty;
chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
identification_t *issuer, *subject;
@@ -1583,7 +1590,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
asn1_wrap(ASN1_SEQUENCE, "m", authorityInfoAccess)));
}
- /* build CA basicConstraint for CA certificates */
+ /* build CA basicConstraint and keyUsage flags for CA certificates */
if (cert->flags & X509_CA)
{
chunk_t pathLenConstraint = chunk_empty;
@@ -1603,6 +1610,13 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
asn1_wrap(ASN1_BOOLEAN, "c",
chunk_from_chars(0xFF)),
pathLenConstraint)));
+ keyUsage = asn1_wrap(ASN1_SEQUENCE, "mmm",
+ asn1_build_known_oid(OID_KEY_USAGE),
+ asn1_wrap(ASN1_BOOLEAN, "c",
+ chunk_from_chars(0xFF)),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_BIT_STRING, "c",
+ chunk_from_chars(0x01, 0x06))));
}
/* add serverAuth extendedKeyUsage flag */
@@ -1663,8 +1677,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
crlDistributionPoints.ptr)
{
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
- asn1_wrap(ASN1_SEQUENCE, "mmmmmmm",
- basicConstraints, subjectKeyIdentifier,
+ asn1_wrap(ASN1_SEQUENCE, "mmmmmmmm",
+ basicConstraints, keyUsage, subjectKeyIdentifier,
authKeyIdentifier, subjectAltNames,
extendedKeyUsage, crlDistributionPoints,
authorityInfoAccess));
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index b9ef3218b..c755d7f63 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -216,14 +216,14 @@ static bool parse(private_x509_crl_t *this)
break;
case CRL_OBJ_VERSION:
this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
- DBG2(" v%d", this->version);
+ DBG2(DBG_LIB, " v%d", this->version);
break;
case CRL_OBJ_SIG_ALG:
sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
break;
case CRL_OBJ_ISSUER:
this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
- DBG2(" '%Y'", this->issuer);
+ DBG2(DBG_LIB, " '%Y'", this->issuer);
break;
case CRL_OBJ_THIS_UPDATE:
this->thisUpdate = asn1_parse_time(object, level);
@@ -248,7 +248,7 @@ static bool parse(private_x509_crl_t *this)
case CRL_OBJ_CRL_ENTRY_CRITICAL:
case CRL_OBJ_CRITICAL:
critical = object.len && *object.ptr;
- DBG2(" %s", critical ? "TRUE" : "FALSE");
+ DBG2(DBG_LIB, " %s", critical ? "TRUE" : "FALSE");
break;
case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
case CRL_OBJ_EXTN_VALUE:
@@ -262,7 +262,8 @@ static bool parse(private_x509_crl_t *this)
{
revoked->reason = *object.ptr;
}
- DBG2(" '%N'", crl_reason_names, revoked->reason);
+ DBG2(DBG_LIB, " '%N'", crl_reason_names,
+ revoked->reason);
}
else if (extn_oid == OID_AUTHORITY_KEY_ID)
{
@@ -286,7 +287,7 @@ static bool parse(private_x509_crl_t *this)
this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
if (this->algorithm != sig_alg)
{
- DBG1(" signature algorithms do not agree");
+ DBG1(DBG_LIB, " signature algorithms do not agree");
goto end;
}
break;
@@ -483,7 +484,7 @@ static bool is_newer(private_x509_crl_t *this, crl_t *that)
if (this->crlNumber.ptr != NULL && that_crlNumber.ptr != NULL)
{
new = chunk_compare(this->crlNumber, that_crlNumber) > 0;
- DBG1(" crl #%#B is %s - existing crl #%#B %s",
+ DBG1(DBG_LIB, " crl #%#B is %s - existing crl #%#B %s",
&this->crlNumber, new ? "newer":"not newer",
&that_crlNumber, new ? "replaced":"retained");
}
@@ -497,7 +498,7 @@ static bool is_newer(private_x509_crl_t *this, crl_t *that)
this_cert->get_validity(this_cert, &now, &this_update, NULL);
that_cert->get_validity(that_cert, &now, &that_update, NULL);
new = this_update > that_update;
- DBG1(" crl from %T is %s - existing crl from %T %s",
+ DBG1(DBG_LIB, " crl from %T is %s - existing crl from %T %s",
&this_update, FALSE, new ? "newer":"not newer",
&that_update, FALSE, new ? "replaced":"retained");
}
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
index f86f87751..c835d5dc8 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
@@ -179,13 +179,14 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
}
else
{
- DBG1("creating OCSP request failed, SHA1 not supported");
+ DBG1(DBG_LIB, "creating OCSP request failed, SHA1 not supported");
}
public->destroy(public);
}
else
{
- DBG1("creating OCSP request failed, CA certificate has no public key");
+ DBG1(DBG_LIB, "creating OCSP request failed, CA certificate has "
+ "no public key");
}
return asn1_wrap(ASN1_SEQUENCE, "m", list);
}
@@ -205,7 +206,7 @@ static chunk_t build_nonce(private_x509_ocsp_request_t *this)
return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
}
- DBG1("creating OCSP request nonce failed, no RNG found");
+ DBG1(DBG_LIB, "creating OCSP request nonce failed, no RNG found");
return chunk_empty;
}
@@ -263,14 +264,14 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
scheme = SIGN_ECDSA_WITH_SHA1_DER;
break;
default:
- DBG1("unable to sign OCSP request, %N signature not supported",
- key_type_names, this->key->get_type(this->key));
+ DBG1(DBG_LIB, "unable to sign OCSP request, %N signature not "
+ "supported", key_type_names, this->key->get_type(this->key));
return chunk_empty;
}
if (!this->key->sign(this->key, scheme, tbsRequest, &signature))
{
- DBG1("creating OCSP signature failed, skipped");
+ DBG1(DBG_LIB, "creating OCSP signature failed, skipped");
return chunk_empty;
}
if (this->cert)
@@ -378,7 +379,7 @@ static id_match_t has_issuer(private_x509_ocsp_request_t *this,
*/
static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer)
{
- DBG1("OCSP request validation not implemented!");
+ DBG1(DBG_LIB, "OCSP request validation not implemented!");
return FALSE;
}
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index 948d7ad85..c70d461df 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -509,7 +509,8 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this,
if (version != OCSP_BASIC_RESPONSE_VERSION)
{
- DBG1(" ocsp ResponseData version %d not supported", version);
+ DBG1(DBG_LIB, " ocsp ResponseData version %d not "
+ "supported", version);
goto end;
}
break;
@@ -517,12 +518,12 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this,
case BASIC_RESPONSE_ID_BY_NAME:
this->responderId = identification_create_from_encoding(
ID_DER_ASN1_DN, object);
- DBG2(" '%Y'", this->responderId);
+ DBG2(DBG_LIB, " '%Y'", this->responderId);
break;
case BASIC_RESPONSE_ID_BY_KEY:
this->responderId = identification_create_from_encoding(
ID_KEY_ID, object);
- DBG2(" '%Y'", this->responderId);
+ DBG2(DBG_LIB, " '%Y'", this->responderId);
break;
case BASIC_RESPONSE_PRODUCED_AT:
this->producedAt = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
@@ -536,7 +537,7 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this,
break;
case BASIC_RESPONSE_CRITICAL:
critical = object.len && *object.ptr;
- DBG2(" %s", critical ? "TRUE" : "FALSE");
+ DBG2(DBG_LIB, " %s", critical ? "TRUE" : "FALSE");
break;
case BASIC_RESPONSE_EXT_VALUE:
if (extn_oid == OID_NONCE)
@@ -622,7 +623,7 @@ static bool parse_OCSPResponse(private_x509_ocsp_response_t *this)
case OCSP_SUCCESSFUL:
break;
default:
- DBG1(" ocsp response status: %N",
+ DBG1(DBG_LIB, " ocsp response status: %N",
ocsp_status_names, status);
goto end;
}
@@ -638,7 +639,8 @@ static bool parse_OCSPResponse(private_x509_ocsp_response_t *this)
parser->get_level(parser)+1);
break;
default:
- DBG1(" ocsp response type %#B not supported", &object);
+ DBG1(DBG_LIB, " ocsp response type %#B not supported",
+ &object);
goto end;
}
break;
@@ -772,9 +774,9 @@ static bool is_newer(certificate_t *this, certificate_t *that)
this->get_validity(this, &now, &this_update, NULL);
that->get_validity(that, &now, &that_update, NULL);
new = this_update > that_update;
- DBG1(" ocsp response from %T is %s - existing ocsp response from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
+ DBG1(DBG_LIB, " ocsp response from %T is %s - existing ocsp response "
+ "from %T %s", &this_update, FALSE, new ? "newer" : "not newer",
+ &that_update, FALSE, new ? "replaced" : "retained");
return new;
}
diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c
index 6d750c98c..1009ec931 100644
--- a/src/libstrongswan/plugins/x509/x509_pkcs10.c
+++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c
@@ -297,7 +297,7 @@ static bool parse_extension_request(private_x509_pkcs10_t *this, chunk_t blob, i
break;
case PKCS10_EXTN_CRITICAL:
critical = object.len && *object.ptr;
- DBG2(" %s", critical ? "TRUE" : "FALSE");
+ DBG2(DBG_LIB, " %s", critical ? "TRUE" : "FALSE");
break;
case PKCS10_EXTN_VALUE:
{
@@ -330,25 +330,25 @@ static bool parse_challengePassword(private_x509_pkcs10_t *this, chunk_t blob, i
if (blob.len < 2)
{
- DBG1("L%d - challengePassword: ASN.1 object smaller than 2 octets",
- level);
+ DBG1(DBG_LIB, "L%d - challengePassword: ASN.1 object smaller "
+ "than 2 octets", level);
return FALSE;
}
tag = *blob.ptr;
if (tag < ASN1_UTF8STRING || tag > ASN1_IA5STRING)
{
- DBG1("L%d - challengePassword: ASN.1 object is not a character string",
- level);
+ DBG1(DBG_LIB, "L%d - challengePassword: ASN.1 object is not "
+ "a character string", level);
return FALSE;
}
if (asn1_length(&blob) == ASN1_INVALID_LENGTH)
{
- DBG1("L%d - challengePassword: ASN.1 object has an invalid length",
- level);
+ DBG1(DBG_LIB, "L%d - challengePassword: ASN.1 object has an "
+ "invalid length", level);
return FALSE;
- }
- DBG2("L%d - challengePassword:", level);
- DBG4(" '%.*s'", blob.len, blob.ptr);
+ }
+ DBG2(DBG_LIB, "L%d - challengePassword:", level);
+ DBG4(DBG_LIB, " '%.*s'", blob.len, blob.ptr);
return TRUE;
}
@@ -406,13 +406,14 @@ static bool parse_certificate_request(private_x509_pkcs10_t *this)
case PKCS10_VERSION:
if (object.len > 0 && *object.ptr != 0)
{
- DBG1("PKCS#10 certificate request format is not version 1");
+ DBG1(DBG_LIB, "PKCS#10 certificate request format is "
+ "not version 1");
goto end;
}
break;
case PKCS10_SUBJECT:
this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
- DBG2(" '%Y'", this->subject);
+ DBG2(DBG_LIB, " '%Y'", this->subject);
break;
case PKCS10_SUBJECT_PUBLIC_KEY_INFO:
this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
@@ -467,7 +468,7 @@ end:
}
else
{
- DBG1("certificate request is not self-signed");
+ DBG1(DBG_LIB, "certificate request is not self-signed");
success = FALSE;
}
}
diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c
index 94c49b1e1..e71c55efc 100644
--- a/src/libstrongswan/plugins/x509/x509_plugin.c
+++ b/src/libstrongswan/plugins/x509/x509_plugin.c
@@ -65,7 +65,7 @@ static void destroy(private_x509_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *x509_plugin_create()
{
private_x509_plugin_t *this = malloc_thing(private_x509_plugin_t);
diff --git a/src/libstrongswan/plugins/x509/x509_plugin.h b/src/libstrongswan/plugins/x509/x509_plugin.h
index fe8c0b31f..e3f959ffa 100644
--- a/src/libstrongswan/plugins/x509/x509_plugin.h
+++ b/src/libstrongswan/plugins/x509/x509_plugin.h
@@ -39,9 +39,4 @@ struct x509_plugin_t {
plugin_t plugin;
};
-/**
- * Create a x509_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** X509_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.am b/src/libstrongswan/plugins/xcbc/Makefile.am
index 515b75031..7de306832 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.am
+++ b/src/libstrongswan/plugins/xcbc/Makefile.am
@@ -3,9 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-xcbc.la
+else
plugin_LTLIBRARIES = libstrongswan-xcbc.la
+endif
-libstrongswan_xcbc_la_SOURCES = xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
+libstrongswan_xcbc_la_SOURCES = \
+ xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
xcbc_prf.h xcbc_prf.c xcbc_signer.h xcbc_signer.c
-libstrongswan_xcbc_la_LDFLAGS = -module -avoid-version
+libstrongswan_xcbc_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in
index 3720aeaeb..c49e2b76a 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.in
+++ b/src/libstrongswan/plugins/xcbc/Makefile.in
@@ -72,7 +72,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_xcbc_la_LIBADD =
am_libstrongswan_xcbc_la_OBJECTS = xcbc_plugin.lo xcbc.lo xcbc_prf.lo \
xcbc_signer.lo
@@ -80,6 +80,8 @@ libstrongswan_xcbc_la_OBJECTS = $(am_libstrongswan_xcbc_la_OBJECTS)
libstrongswan_xcbc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_xcbc_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_xcbc_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_xcbc_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -218,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -254,8 +257,10 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-xcbc.la
-libstrongswan_xcbc_la_SOURCES = xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xcbc.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xcbc.la
+libstrongswan_xcbc_la_SOURCES = \
+ xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
xcbc_prf.h xcbc_prf.c xcbc_signer.h xcbc_signer.c
libstrongswan_xcbc_la_LDFLAGS = -module -avoid-version
@@ -293,6 +298,15 @@ $(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)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -325,7 +339,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-xcbc.la: $(libstrongswan_xcbc_la_OBJECTS) $(libstrongswan_xcbc_la_DEPENDENCIES)
- $(libstrongswan_xcbc_la_LINK) -rpath $(plugindir) $(libstrongswan_xcbc_la_OBJECTS) $(libstrongswan_xcbc_la_LIBADD) $(LIBS)
+ $(libstrongswan_xcbc_la_LINK) $(am_libstrongswan_xcbc_la_rpath) $(libstrongswan_xcbc_la_OBJECTS) $(libstrongswan_xcbc_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -481,8 +495,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -553,18 +567,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
index 3eb7f0927..9d903bfaa 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
+++ b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
@@ -47,7 +47,7 @@ static void destroy(private_xcbc_plugin_t *this)
/*
* see header file
*/
-plugin_t *plugin_create()
+plugin_t *xcbc_plugin_create()
{
private_xcbc_plugin_t *this = malloc_thing(private_xcbc_plugin_t);
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_plugin.h b/src/libstrongswan/plugins/xcbc/xcbc_plugin.h
index 803d847aa..9824088c6 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc_plugin.h
+++ b/src/libstrongswan/plugins/xcbc/xcbc_plugin.h
@@ -39,9 +39,4 @@ struct xcbc_plugin_t {
plugin_t plugin;
};
-/**
- * Create a xcbc_plugin instance.
- */
-plugin_t *plugin_create();
-
#endif /** XCBC_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/printf_hook.c b/src/libstrongswan/printf_hook.c
index 0b516c99e..037f0b918 100644
--- a/src/libstrongswan/printf_hook.c
+++ b/src/libstrongswan/printf_hook.c
@@ -16,8 +16,8 @@
#include "printf_hook.h"
-#include <utils.h>
-#include <debug.h>
+#include "utils.h"
+#include "debug.h"
#include <stdio.h>
#include <stdarg.h>
@@ -333,7 +333,8 @@ static void add_handler(private_printf_hook_t *this, char spec,
if (!IS_VALID_SPEC(spec))
{
- DBG1("'%c' is not a valid printf hook specifier, not registered!", spec);
+ DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
+ "not registered!", spec);
return;
}
@@ -345,7 +346,8 @@ static void add_handler(private_printf_hook_t *this, char spec,
{
if (++i >= ARGS_MAX)
{
- DBG1("Too many arguments for printf hook with specifier '%c', not registered!", spec);
+ DBG1(DBG_LIB, "Too many arguments for printf hook with "
+ "specifier '%c', not registered!", spec);
va_end(args);
free(handler);
return;
@@ -427,7 +429,7 @@ printf_hook_t *printf_hook_create()
#ifdef USE_VSTR
if (!vstr_init())
{
- DBG1("failed to initialize Vstr library!");
+ DBG1(DBG_LIB, "failed to initialize Vstr library!");
free(this);
return NULL;
}
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
index b5964b541..257da3f24 100644
--- a/src/libstrongswan/selectors/traffic_selector.h
+++ b/src/libstrongswan/selectors/traffic_selector.h
@@ -74,8 +74,8 @@ struct traffic_selector_t {
*
* @param other traffic selector to compare
* @return
- * - created subset of them
- * - or NULL if no match between this and other
+ * - created subset of them
+ * - or NULL if no match between this and other
*/
traffic_selector_t *(*get_subset) (traffic_selector_t *this,
traffic_selector_t *other);
@@ -173,7 +173,7 @@ struct traffic_selector_t {
* Compare two traffic selectors for equality.
*
* @param other ts to compare with this
- * @return TRUE if equal, FALSE otherwise
+ * @return TRUE if equal, FALSE otherwise
*/
bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
@@ -215,15 +215,15 @@ struct traffic_selector_t {
/**
* Create a new traffic selector using human readable params.
*
- * @param protocol protocol for this ts, such as TCP or UDP
+ * @param protocol protocol for this ts, such as TCP or UDP
* @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
* @param from_addr start of address range as string
* @param from_port port number in host order
* @param to_addr end of address range as string
* @param to_port port number in host order
* @return
- * - traffic_selector_t object
- * - NULL if invalid address strings/protocol
+ * - traffic_selector_t object
+ * - NULL if invalid address strings/protocol
*/
traffic_selector_t *traffic_selector_create_from_string(
u_int8_t protocol, ts_type_t type,
@@ -237,11 +237,11 @@ traffic_selector_t *traffic_selector_create_from_string(
* But the parser gives us this data in this format, so we
* don't have to convert twice.
*
- * @param protocol protocol for this ts, such as TCP or UDP
+ * @param protocol protocol for this ts, such as TCP or UDP
* @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
- * @param from_addr start of address range, network order
+ * @param from_address start of address range, network order
* @param from_port port number, host order
- * @param to_addr end of address range, network order
+ * @param to_address end of address range, network order
* @param to_port port number, host order
* @return traffic_selector_t object
*/
@@ -273,11 +273,11 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
*
* @param net subnet to use
* @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation
- * @param protocol protocol for this ts, such as TCP or UDP
+ * @param protocol protocol for this ts, such as TCP or UDP
* @param port port number, host order
* @return
- * - traffic_selector_t object
- * - NULL if address family of net not supported
+ * - traffic_selector_t object
+ * - NULL if address family of net not supported
*/
traffic_selector_t *traffic_selector_create_from_subnet(
host_t *net, u_int8_t netbits,
@@ -295,8 +295,8 @@ traffic_selector_t *traffic_selector_create_from_subnet(
* @param from_port start of allowed port range
* @param to_port end of range
* @return
- * - traffic_selector_t object
- * - NULL if type not supported
+ * - traffic_selector_t object
+ * - NULL if type not supported
*/
traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
u_int16_t from_port, u_int16_t to_port);
diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c
index 4a822bcbf..610e2b8ea 100644
--- a/src/libstrongswan/settings.c
+++ b/src/libstrongswan/settings.c
@@ -21,8 +21,8 @@
#include "settings.h"
-#include <debug.h>
-#include <utils/linked_list.h>
+#include "debug.h"
+#include "utils/linked_list.h"
typedef struct private_settings_t private_settings_t;
@@ -293,8 +293,8 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, ..
if (value)
{
errno = 0;
- timeval = strtol(value, &endptr, 10);
- if (errno == 0 && timeval >= 0)
+ timeval = strtoul(value, &endptr, 10);
+ if (errno == 0)
{
switch (*endptr)
{
@@ -497,7 +497,7 @@ static section_t* parse_section(char **text, char *name)
continue;
}
}
- DBG1("matching '}' not found near %s", *text);
+ DBG1(DBG_LIB, "matching '}' not found near %s", *text);
break;
case '=':
if (parse(text, "\t ", "\n", NULL, &value))
@@ -508,7 +508,7 @@ static section_t* parse_section(char **text, char *name)
section->kv->insert_last(section->kv, kv);
continue;
}
- DBG1("parsing value failed near %s", *text);
+ DBG1(DBG_LIB, "parsing value failed near %s", *text);
break;
case '#':
parse(text, "", "\n", NULL, &value);
@@ -566,7 +566,7 @@ settings_t *settings_create(char *file)
fd = fopen(file, "r");
if (fd == NULL)
{
- DBG1("'%s' does not exist or is not readable", file);
+ DBG1(DBG_LIB, "'%s' does not exist or is not readable", file);
return &this->public;
}
fseek(fd, 0, SEEK_END);
diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h
index 9e8d75cc0..f274fb33c 100644
--- a/src/libstrongswan/settings.h
+++ b/src/libstrongswan/settings.h
@@ -23,8 +23,8 @@
typedef struct settings_t settings_t;
-#include <utils.h>
-#include <utils/enumerator.h>
+#include "utils.h"
+#include "utils/enumerator.h"
/**
* Generic configuration options read from a config file.
diff --git a/src/libstrongswan/threading/mutex.c b/src/libstrongswan/threading/mutex.c
index a35695624..8597abb44 100644
--- a/src/libstrongswan/threading/mutex.c
+++ b/src/libstrongswan/threading/mutex.c
@@ -108,7 +108,7 @@ static void lock(private_mutex_t *this)
err = pthread_mutex_lock(&this->mutex);
if (err)
{
- DBG1("!!! MUTEX LOCK ERROR: %s !!!", strerror(err));
+ DBG1(DBG_LIB, "!!! MUTEX LOCK ERROR: %s !!!", strerror(err));
}
profiler_end(&this->profile);
}
@@ -123,7 +123,7 @@ static void unlock(private_mutex_t *this)
err = pthread_mutex_unlock(&this->mutex);
if (err)
{
- DBG1("!!! MUTEX UNLOCK ERROR: %s !!!", strerror(err));
+ DBG1(DBG_LIB, "!!! MUTEX UNLOCK ERROR: %s !!!", strerror(err));
}
}
diff --git a/src/libstrongswan/threading/rwlock.c b/src/libstrongswan/threading/rwlock.c
index ee9fb10be..cec43f59c 100644
--- a/src/libstrongswan/threading/rwlock.c
+++ b/src/libstrongswan/threading/rwlock.c
@@ -98,7 +98,7 @@ static void read_lock(private_rwlock_t *this)
err = pthread_rwlock_rdlock(&this->rwlock);
if (err != 0)
{
- DBG1("!!! RWLOCK READ LOCK ERROR: %s !!!", strerror(err));
+ DBG1(DBG_LIB, "!!! RWLOCK READ LOCK ERROR: %s !!!", strerror(err));
}
profiler_end(&this->profile);
}
@@ -114,7 +114,7 @@ static void write_lock(private_rwlock_t *this)
err = pthread_rwlock_wrlock(&this->rwlock);
if (err != 0)
{
- DBG1("!!! RWLOCK WRITE LOCK ERROR: %s !!!", strerror(err));
+ DBG1(DBG_LIB, "!!! RWLOCK WRITE LOCK ERROR: %s !!!", strerror(err));
}
profiler_end(&this->profile);
}
@@ -137,7 +137,7 @@ static void rw_unlock(private_rwlock_t *this)
err = pthread_rwlock_unlock(&this->rwlock);
if (err != 0)
{
- DBG1("!!! RWLOCK UNLOCK ERROR: %s !!!", strerror(err));
+ DBG1(DBG_LIB, "!!! RWLOCK UNLOCK ERROR: %s !!!", strerror(err));
}
}
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c
index bbfb2c2c6..3751bb749 100644
--- a/src/libstrongswan/threading/thread.c
+++ b/src/libstrongswan/threading/thread.c
@@ -155,7 +155,7 @@ static void cancel(private_thread_t *this)
if (pthread_equal(this->thread_id, pthread_self()))
{
this->mutex->unlock(this->mutex);
- DBG1("!!! CANNOT CANCEL CURRENT THREAD !!!");
+ DBG1(DBG_LIB, "!!! CANNOT CANCEL CURRENT THREAD !!!");
return;
}
#ifdef HAVE_PTHREAD_CANCEL
@@ -180,7 +180,7 @@ static void _kill(private_thread_t *this, int sig)
* returned, so depending on the signal, the lock might not get
* unlocked. */
this->mutex->unlock(this->mutex);
- DBG1("!!! CANNOT SEND SIGNAL TO CURRENT THREAD !!!");
+ DBG1(DBG_LIB, "!!! CANNOT SEND SIGNAL TO CURRENT THREAD !!!");
return;
}
pthread_kill(this->thread_id, sig);
@@ -209,13 +209,13 @@ static void *join(private_thread_t *this)
if (pthread_equal(this->thread_id, pthread_self()))
{
this->mutex->unlock(this->mutex);
- DBG1("!!! CANNOT JOIN CURRENT THREAD !!!");
+ DBG1(DBG_LIB, "!!! CANNOT JOIN CURRENT THREAD !!!");
return NULL;
}
if (this->detached_or_joined)
{
this->mutex->unlock(this->mutex);
- DBG1("!!! CANNOT JOIN DETACHED THREAD !!!");
+ DBG1(DBG_LIB, "!!! CANNOT JOIN DETACHED THREAD !!!");
return NULL;
}
thread_id = this->thread_id;
@@ -299,7 +299,8 @@ thread_t *thread_create(thread_main_t main, void *arg)
this->arg = arg;
if (pthread_create(&this->thread_id, NULL, (void*)thread_main, this) != 0)
{
- DBG1("failed to create thread!");
+ DBG1(DBG_LIB, "failed to create thread!");
+ this->mutex->lock(this->mutex);
thread_destroy(this);
return NULL;
}
@@ -354,7 +355,7 @@ void thread_cleanup_pop(bool execute)
(void**)&handler) != SUCCESS)
{
this->mutex->unlock(this->mutex);
- DBG1("!!! THREAD CLEANUP ERROR !!!");
+ DBG1(DBG_LIB, "!!! THREAD CLEANUP ERROR !!!");
return;
}
this->mutex->unlock(this->mutex);
@@ -433,6 +434,7 @@ void threads_init()
void threads_deinit()
{
private_thread_t *main_thread = (private_thread_t*)thread_current();
+ main_thread->mutex->lock(main_thread->mutex);
thread_destroy(main_thread);
current_thread->destroy(current_thread);
id_mutex->destroy(id_mutex);
diff --git a/src/libstrongswan/threading/thread.h b/src/libstrongswan/threading/thread.h
index 6bf8fac79..31b9e1b3a 100644
--- a/src/libstrongswan/threading/thread.h
+++ b/src/libstrongswan/threading/thread.h
@@ -24,6 +24,12 @@
typedef struct thread_t thread_t;
#ifdef __APPLE__
+/* thread_create is a syscall used to create Mach kernel threads and although
+ * there are no errors or warnings during compilation or linkage the dynamic
+ * linker does not use our implementation, therefore we rename it here
+ */
+#define thread_create(main, arg) strongswan_thread_create(main, arg)
+
/* on Mac OS X 10.5 several system calls we use are no cancellation points.
* fortunately, select isn't one of them, so we wrap some of the others with
* calls to select(2).
diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c
index e331ac0d0..63958593d 100644
--- a/src/libstrongswan/utils.c
+++ b/src/libstrongswan/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -25,8 +25,8 @@
#include <dirent.h>
#include <time.h>
-#include <enum.h>
-#include <debug.h>
+#include "enum.h"
+#include "debug.h"
ENUM(status_names, SUCCESS, DESTROY_ME,
"SUCCESS",
@@ -119,9 +119,31 @@ void *memstr(const void *haystack, const char *needle, size_t n)
/**
* Described in header.
*/
+char* translate(char *str, const char *from, const char *to)
+{
+ char *pos = str;
+ if (strlen(from) != strlen(to))
+ {
+ return str;
+ }
+ while (pos && *pos)
+ {
+ char *match;
+ if ((match = strchr(from, *pos)) != NULL)
+ {
+ *pos = to[match - from];
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
+ * Described in header.
+ */
bool mkdir_p(const char *path, mode_t mode)
{
- size_t len;
+ int len;
char *pos, full[PATH_MAX];
pos = full;
if (!path || *path == '\0')
@@ -131,7 +153,7 @@ bool mkdir_p(const char *path, mode_t mode)
len = snprintf(full, sizeof(full)-1, "%s", path);
if (len < 0 || len >= sizeof(full)-1)
{
- DBG1("path string %s too long", path);
+ DBG1(DBG_LIB, "path string %s too long", path);
return FALSE;
}
/* ensure that the path ends with a '/' */
@@ -152,7 +174,7 @@ bool mkdir_p(const char *path, mode_t mode)
{
if (mkdir(full, mode) < 0)
{
- DBG1("failed to create directory %s", full);
+ DBG1(DBG_LIB, "failed to create directory %s", full);
return FALSE;
}
}
diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h
index 964cbd1d2..04551835e 100644
--- a/src/libstrongswan/utils.h
+++ b/src/libstrongswan/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -29,7 +29,7 @@
#include <arpa/inet.h>
#include <string.h>
-#include <enum.h>
+#include "enum.h"
/**
* strongSwan program return codes
@@ -125,7 +125,7 @@
#define METHOD(iface, name, ret, this, ...) \
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
- const static typeof(name) *_##name = (const typeof(name)*)name; \
+ static const typeof(name) *_##name = (const typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
@@ -134,7 +134,7 @@
#define METHOD2(iface1, iface2, name, ret, this, ...) \
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
- const static typeof(name) *_##name = (const typeof(name)*)name; \
+ static const typeof(name) *_##name = (const typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
@@ -150,7 +150,7 @@
/**
* Ignore result of functions tagged with warn_unused_result attributes
*/
-#define ignore_result(call) { if(call); }
+#define ignore_result(call) { if(call){}; }
/**
* Assign a function as a class method
@@ -311,6 +311,14 @@ void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
void *memstr(const void *haystack, const char *needle, size_t n);
/**
+ * Translates the characters in the given string, searching for characters
+ * in 'from' and mapping them to characters in 'to'.
+ * The two characters sets 'from' and 'to' must contain the same number of
+ * characters.
+ */
+char *translate(char *str, const char *from, const char *to);
+
+/**
* Creates a directory and all required parent directories.
*
* @param path path to the new directory
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c
index 7efdd883e..fb461b448 100644
--- a/src/libstrongswan/utils/enumerator.c
+++ b/src/libstrongswan/utils/enumerator.c
@@ -76,7 +76,8 @@ static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
char **absolute, struct stat *st)
{
struct dirent *entry = readdir(this->dir);
- size_t len, remaining;
+ size_t remaining;
+ int len;
if (!entry)
{
@@ -96,7 +97,8 @@ static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
len = snprintf(this->full_end, remaining, "%s", entry->d_name);
if (len < 0 || len >= remaining)
{
- DBG1("buffer too small to enumerate file '%s'", entry->d_name);
+ DBG1(DBG_LIB, "buffer too small to enumerate file '%s'",
+ entry->d_name);
return FALSE;
}
if (absolute)
@@ -107,7 +109,8 @@ static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
{
if (stat(this->full, st))
{
- DBG1("stat() on '%s' failed: %s", this->full, strerror(errno));
+ DBG1(DBG_LIB, "stat() on '%s' failed: %s", this->full,
+ strerror(errno));
return FALSE;
}
}
@@ -120,7 +123,7 @@ static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
*/
enumerator_t* enumerator_create_directory(char *path)
{
- size_t len;
+ int len;
dir_enum_t *this = malloc_thing(dir_enum_t);
this->public.enumerate = (void*)enumerate_dir_enum;
this->public.destroy = (void*)destroy_dir_enum;
@@ -132,7 +135,7 @@ enumerator_t* enumerator_create_directory(char *path)
len = snprintf(this->full, sizeof(this->full)-1, "%s", path);
if (len < 0 || len >= sizeof(this->full)-1)
{
- DBG1("path string '%s' too long", path);
+ DBG1(DBG_LIB, "path string '%s' too long", path);
free(this);
return NULL;
}
@@ -147,7 +150,7 @@ enumerator_t* enumerator_create_directory(char *path)
this->dir = opendir(path);
if (this->dir == NULL)
{
- DBG1("opening directory '%s' failed: %s", path, strerror(errno));
+ DBG1(DBG_LIB, "opening directory '%s' failed: %s", path, strerror(errno));
free(this);
return NULL;
}
diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h
index 3056498b1..537bf69e1 100644
--- a/src/libstrongswan/utils/enumerator.h
+++ b/src/libstrongswan/utils/enumerator.h
@@ -23,7 +23,7 @@
typedef struct enumerator_t enumerator_t;
-#include <utils.h>
+#include "../utils.h"
/**
* Enumerate is simpler, but more flexible than iterator.
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c
index a610b3a4d..112d07e5c 100644
--- a/src/libstrongswan/utils/host.c
+++ b/src/libstrongswan/utils/host.c
@@ -482,7 +482,7 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port)
error = getaddrinfo(string, NULL, &hints, &result);
if (error != 0)
{
- DBG1("resolving '%s' failed: %s", string, gai_strerror(error));
+ DBG1(DBG_LIB, "resolving '%s' failed: %s", string, gai_strerror(error));
return NULL;
}
/* result is a linked list, but we use only the first address */
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index b0da340bc..6a3c3936c 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -798,7 +798,7 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
return print_in_hook(dst, len, "%*s", spec->width, buf);
}
-METHOD(identification_t, clone, identification_t*,
+METHOD(identification_t, clone_, identification_t*,
private_identification_t *this)
{
private_identification_t *clone = malloc_thing(private_identification_t);
@@ -830,7 +830,7 @@ static private_identification_t *identification_create(id_type_t type)
.get_encoding = _get_encoding,
.get_type = _get_type,
.create_part_enumerator = _create_part_enumerator,
- .clone = _clone,
+ .clone = _clone_,
.destroy = _destroy,
},
.type = type,
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 2c2a36af3..2f8a7187c 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -167,6 +167,7 @@ char *whitelist[] = {
"tzset",
"inet_ntoa",
"strerror",
+ "getprotobyname",
"getprotobynumber",
"getservbyport",
"getservbyname",
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index bf528caa0..d8f635c62 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -80,14 +80,15 @@ bool from(private_options_t *this, char *filename, int *argcp, char **argvp[],
this->nuses++;
if (this->nuses >= MAX_USES)
{
- DBG1("optionsfrom called %d times by \"%s\" - looping?", this->nuses + 1, (*argvp)[0]);
+ DBG1(DBG_LIB, "optionsfrom called %d times by \"%s\" - looping?",
+ this->nuses + 1, (*argvp)[0]);
return FALSE;
}
fd = fopen(filename, "r");
if (fd == NULL)
{
- DBG1("optionsfrom: unable to open file '%s': %s",
+ DBG1(DBG_LIB, "optionsfrom: unable to open file '%s': %s",
filename, strerror(errno));
return FALSE;
}
@@ -132,7 +133,7 @@ bool from(private_options_t *this, char *filename, int *argcp, char **argvp[],
line.len--;
if (!extract_token(&token, delimiter, &line))
{
- DBG1("optionsfrom: missing terminator at %s:%d",
+ DBG1(DBG_LIB, "optionsfrom: missing terminator at %s:%d",
filename, linepos);
good = FALSE;
break;
diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am
index e6c31e9b4..e67335673 100644
--- a/src/manager/Makefile.am
+++ b/src/manager/Makefile.am
@@ -10,7 +10,8 @@ controller/control_controller.c controller/control_controller.h \
controller/config_controller.c controller/config_controller.h \
controller/gateway_controller.c controller/gateway_controller.h
-manager_fcgi_LDADD = $(top_builddir)/src/libfast/libfast.la ${xml_LIBS}
+manager_fcgi_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libfast/libfast.la ${xml_LIBS}
+main.o : $(top_builddir)/config.status
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libfast ${xml_CFLAGS}
AM_CFLAGS = -rdynamic \
diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in
index 20438acc3..54e2cc11c 100644
--- a/src/manager/Makefile.in
+++ b/src/manager/Makefile.in
@@ -68,8 +68,9 @@ am_manager_fcgi_OBJECTS = main.$(OBJEXT) manager.$(OBJEXT) \
gateway_controller.$(OBJEXT)
manager_fcgi_OBJECTS = $(am_manager_fcgi_OBJECTS)
am__DEPENDENCIES_1 =
-manager_fcgi_DEPENDENCIES = $(top_builddir)/src/libfast/libfast.la \
- $(am__DEPENDENCIES_1)
+manager_fcgi_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libfast/libfast.la $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -235,6 +236,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -278,7 +280,7 @@ controller/control_controller.c controller/control_controller.h \
controller/config_controller.c controller/config_controller.h \
controller/gateway_controller.c controller/gateway_controller.h
-manager_fcgi_LDADD = $(top_builddir)/src/libfast/libfast.la ${xml_LIBS}
+manager_fcgi_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libfast/libfast.la ${xml_LIBS}
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libfast ${xml_CFLAGS}
AM_CFLAGS = -rdynamic \
-DIPSECDIR=\"${ipsecdir}\" \
@@ -881,6 +883,7 @@ uninstall-am: uninstall-managerPROGRAMS \
uninstall-manager_templates_ikesaDATA \
uninstall-manager_templates_staticDATA
+main.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/manager/main.c b/src/manager/main.c
index 1f5c45113..5c297cf0c 100644
--- a/src/manager/main.c
+++ b/src/manager/main.c
@@ -48,7 +48,8 @@ int main (int arc, char *argv[])
database = lib->settings->get_str(lib->settings, "manager.database", NULL);
if (!database)
{
- DBG1("database URI undefined, set manager.database in strongswan.conf");
+ DBG1(DBG_LIB, "database URI undefined, set manager.database "
+ "in strongswan.conf");
return 1;
}
diff --git a/src/medsrv/Makefile.am b/src/medsrv/Makefile.am
index 9f5c9e2f7..bdec08190 100644
--- a/src/medsrv/Makefile.am
+++ b/src/medsrv/Makefile.am
@@ -7,7 +7,8 @@ main.c filter/auth_filter.c filter/auth_filter.h \
controller/user_controller.c controller/user_controller.h \
controller/peer_controller.c controller/peer_controller.h
-medsrv_fcgi_LDADD = $(top_builddir)/src/libfast/libfast.la
+medsrv_fcgi_LDADD = $(top_srcdir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libfast/libfast.la
+main.o : $(top_builddir)/config.status
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libfast
AM_CFLAGS = -rdynamic \
diff --git a/src/medsrv/Makefile.in b/src/medsrv/Makefile.in
index 8f602930d..2f79ca4d4 100644
--- a/src/medsrv/Makefile.in
+++ b/src/medsrv/Makefile.in
@@ -62,7 +62,9 @@ am_medsrv_fcgi_OBJECTS = user.$(OBJEXT) main.$(OBJEXT) \
auth_filter.$(OBJEXT) user_controller.$(OBJEXT) \
peer_controller.$(OBJEXT)
medsrv_fcgi_OBJECTS = $(am_medsrv_fcgi_OBJECTS)
-medsrv_fcgi_DEPENDENCIES = $(top_builddir)/src/libfast/libfast.la
+medsrv_fcgi_DEPENDENCIES = \
+ $(top_srcdir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libfast/libfast.la
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -224,6 +226,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -264,7 +267,7 @@ main.c filter/auth_filter.c filter/auth_filter.h \
controller/user_controller.c controller/user_controller.h \
controller/peer_controller.c controller/peer_controller.h
-medsrv_fcgi_LDADD = $(top_builddir)/src/libfast/libfast.la
+medsrv_fcgi_LDADD = $(top_srcdir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libfast/libfast.la
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libfast
AM_CFLAGS = -rdynamic \
-DIPSECDIR=\"${ipsecdir}\" \
@@ -751,6 +754,7 @@ uninstall-am: uninstall-medsrvPROGRAMS uninstall-medsrv_templatesDATA \
uninstall-medsrv_templates_staticDATA \
uninstall-medsrv_templates_userDATA
+main.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/openac/Makefile.am b/src/openac/Makefile.am
index ca6238258..a278cdd17 100644
--- a/src/openac/Makefile.am
+++ b/src/openac/Makefile.am
@@ -7,4 +7,4 @@ AM_CFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\" \
-DPLUGINS=\""${libstrongswan_plugins}\""
openac_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
-
+openac.o : $(top_builddir)/config.status
diff --git a/src/openac/Makefile.in b/src/openac/Makefile.in
index 08f621395..9f0f96561 100644
--- a/src/openac/Makefile.in
+++ b/src/openac/Makefile.in
@@ -220,6 +220,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -633,6 +634,7 @@ uninstall-man: uninstall-man8
tags uninstall uninstall-am uninstall-ipsecPROGRAMS \
uninstall-man uninstall-man8
+openac.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/openac/openac.c b/src/openac/openac.c
index 2b9270ff9..a280192c2 100755
--- a/src/openac/openac.c
+++ b/src/openac/openac.c
@@ -105,7 +105,8 @@ static chunk_t read_serial(void)
}
else
{
- DBG1(" file '%s' does not exist yet - serial number set to 01", OPENAC_SERIAL);
+ DBG1(DBG_LIB, " file '%s' does not exist yet - serial number "
+ "set to 01", OPENAC_SERIAL);
}
if (!serial.len)
{
@@ -129,7 +130,7 @@ static void write_serial(chunk_t serial)
{
chunk_t hex_serial;
- DBG1(" serial number is %#B", &serial);
+ DBG1(DBG_LIB, " serial number is %#B", &serial);
hex_serial = chunk_to_hex(serial, NULL, FALSE);
fprintf(fd, "%.*s\n", hex_serial.len, hex_serial.ptr);
fclose(fd);
@@ -137,7 +138,7 @@ static void write_serial(chunk_t serial)
}
else
{
- DBG1(" could not open file '%s' for writing", OPENAC_SERIAL);
+ DBG1(DBG_LIB, " could not open file '%s' for writing", OPENAC_SERIAL);
}
}
@@ -151,7 +152,7 @@ static bool stderr_quiet = FALSE;
/**
* openac dbg function
*/
-static void openac_dbg(int level, char *fmt, ...)
+static void openac_dbg(debug_t group, level_t level, char *fmt, ...)
{
int priority = LOG_INFO;
char buffer[8192];
@@ -431,7 +432,7 @@ int main(int argc, char **argv)
goto end;
}
- DBG1("starting openac (strongSwan Version %s)", VERSION);
+ DBG1(DBG_LIB, "starting openac (strongSwan Version %s)", VERSION);
/* load the signer's RSA private key */
if (keyfile != NULL)
@@ -444,7 +445,7 @@ int main(int argc, char **argv)
{
goto end;
}
- DBG1(" loaded private key file '%s'", keyfile);
+ DBG1(DBG_LIB, " loaded private key file '%s'", keyfile);
}
/* load the signer's X.509 certificate */
diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am
index a471b6477..8eac07afc 100644
--- a/src/pki/Makefile.am
+++ b/src/pki/Makefile.am
@@ -7,9 +7,11 @@ pki_SOURCES = pki.c pki.h command.c command.h \
commands/pub.c \
commands/req.c \
commands/self.c \
- commands/verify.c
+ commands/verify.c
pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+pki.o : $(top_builddir)/config.status
+
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = \
-DPLUGINS=\""${libstrongswan_plugins}\""
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index 1261d7fa8..522b9e887 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -196,6 +196,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -237,7 +238,7 @@ pki_SOURCES = pki.c pki.h command.c command.h \
commands/pub.c \
commands/req.c \
commands/self.c \
- commands/verify.c
+ commands/verify.c
pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
INCLUDES = -I$(top_srcdir)/src/libstrongswan
@@ -667,6 +668,7 @@ uninstall-am: uninstall-ipsecPROGRAMS
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-ipsecPROGRAMS
+pki.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/pki/commands/gen.c b/src/pki/commands/gen.c
index 16d8d48d4..b2769da54 100644
--- a/src/pki/commands/gen.c
+++ b/src/pki/commands/gen.c
@@ -47,7 +47,7 @@ static int gen()
return command_usage("invalid key type");
}
continue;
- case 'o':
+ case 'f':
if (!get_form(arg, &form, FALSE))
{
return command_usage("invalid key output format");
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index 07ab9066a..fcd758f87 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -161,7 +161,7 @@ static int issue()
}
}
- DBG2("Reading ca certificate:");
+ DBG2(DBG_LIB, "Reading ca certificate:");
ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, cacert, BUILD_END);
if (!ca)
@@ -182,7 +182,7 @@ static int issue()
goto end;
}
- DBG2("Reading ca private key:");
+ DBG2(DBG_LIB, "Reading ca private key:");
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
public->get_type(public),
BUILD_FROM_FILE, cakey, BUILD_END);
@@ -212,6 +212,11 @@ static int issue()
goto end;
}
rng->allocate_bytes(rng, 8, &serial);
+ while (*serial.ptr == 0x00)
+ {
+ /* we don't accept a serial number with leading zeroes */
+ rng->get_bytes(rng, 1, serial.ptr);
+ }
rng->destroy(rng);
}
@@ -221,7 +226,7 @@ static int issue()
identification_t *subjectAltName;
pkcs10_t *req;
- DBG2("Reading certificate request");
+ DBG2(DBG_LIB, "Reading certificate request");
if (file)
{
cert_req = lib->creds->create(lib->creds, CRED_CERTIFICATE,
@@ -261,7 +266,7 @@ static int issue()
}
else
{
- DBG2("Reading public key:");
+ DBG2(DBG_LIB, "Reading public key:");
if (file)
{
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c
index 30ae23be5..d283daa6a 100644
--- a/src/pki/commands/self.c
+++ b/src/pki/commands/self.c
@@ -158,6 +158,11 @@ static int self()
goto end;
}
rng->allocate_bytes(rng, 8, &serial);
+ while (*serial.ptr == 0x00)
+ {
+ /* we don't accept a serial number with leading zeroes */
+ rng->get_bytes(rng, 1, serial.ptr);
+ }
rng->destroy(rng);
}
not_before = time(NULL);
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
index b83e4be33..a264e642e 100644
--- a/src/pluto/Makefile.am
+++ b/src/pluto/Makefile.am
@@ -46,6 +46,7 @@ state.c state.h \
timer.c timer.h \
vendor.c vendor.h \
virtual.c virtual.h \
+whack_attribute.c whack_attribute.h \
xauth.c xauth.h \
x509.c x509.h \
builder.c builder.h \
@@ -53,13 +54,17 @@ rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
+plutomain.o : $(top_builddir)/config.status
+
LIBSTRONGSWANDIR=$(top_builddir)/src/libstrongswan
LIBFREESWANDIR=$(top_builddir)/src/libfreeswan
+LIBHYDRADIR=$(top_builddir)/src/libhydra
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
+-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/whack
AM_CFLAGS = \
@@ -75,6 +80,7 @@ AM_CFLAGS = \
pluto_LDADD = \
$(LIBSTRONGSWANDIR)/libstrongswan.la \
$(LIBFREESWANDIR)/libfreeswan.a \
+$(LIBHYDRADIR)/libhydra.la \
-lresolv $(PTHREADLIB) $(DLLIB)
_pluto_adns_LDADD = \
diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in
index c93756c44..47be9acf7 100644
--- a/src/pluto/Makefile.in
+++ b/src/pluto/Makefile.in
@@ -94,12 +94,13 @@ am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) ca.$(OBJEXT) \
pkcs7.$(OBJEXT) plutomain.$(OBJEXT) rcv_whack.$(OBJEXT) \
server.$(OBJEXT) smartcard.$(OBJEXT) spdb.$(OBJEXT) \
state.$(OBJEXT) timer.$(OBJEXT) vendor.$(OBJEXT) \
- virtual.$(OBJEXT) xauth.$(OBJEXT) x509.$(OBJEXT) \
- builder.$(OBJEXT)
+ virtual.$(OBJEXT) whack_attribute.$(OBJEXT) xauth.$(OBJEXT) \
+ x509.$(OBJEXT) builder.$(OBJEXT)
pluto_OBJECTS = $(am_pluto_OBJECTS)
pluto_DEPENDENCIES = $(LIBSTRONGSWANDIR)/libstrongswan.la \
- $(LIBFREESWANDIR)/libfreeswan.a $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ $(LIBFREESWANDIR)/libfreeswan.a $(LIBHYDRADIR)/libhydra.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -263,6 +264,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -339,6 +341,7 @@ state.c state.h \
timer.c timer.h \
vendor.c vendor.h \
virtual.c virtual.h \
+whack_attribute.c whack_attribute.h \
xauth.c xauth.h \
x509.c x509.h \
builder.c builder.h \
@@ -347,10 +350,12 @@ rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
LIBSTRONGSWANDIR = $(top_builddir)/src/libstrongswan
LIBFREESWANDIR = $(top_builddir)/src/libfreeswan
+LIBHYDRADIR = $(top_builddir)/src/libhydra
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
+-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/whack
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
@@ -362,8 +367,8 @@ AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
$(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_7)
pluto_LDADD = $(LIBSTRONGSWANDIR)/libstrongswan.la \
- $(LIBFREESWANDIR)/libfreeswan.a -lresolv $(PTHREADLIB) \
- $(DLLIB) $(am__append_6)
+ $(LIBFREESWANDIR)/libfreeswan.a $(LIBHYDRADIR)/libhydra.la \
+ -lresolv $(PTHREADLIB) $(DLLIB) $(am__append_6)
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
-lresolv $(DLLIB)
@@ -501,6 +506,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whack_attribute.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth.Po@am__quote@
@@ -826,6 +832,8 @@ uninstall-man: uninstall-man5 uninstall-man8
uninstall-man8
+plutomain.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/pluto/ac.c b/src/pluto/ac.c
index d8b16112f..3ee05d213 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -88,16 +88,17 @@ bool ac_verify_cert(certificate_t *cert, bool strict)
cert_t *aacert;
time_t notBefore, valid_until;
- DBG1("holder: '%Y'", subject);
- DBG1("issuer: '%Y'", issuer);
+ DBG1(DBG_LIB, "holder: '%Y'", subject);
+ DBG1(DBG_LIB, "issuer: '%Y'", issuer);
if (!cert->get_validity(cert, NULL, NULL, &valid_until))
{
- DBG1("attribute certificate is invalid (valid from %T to %T)",
+ DBG1(DBG_LIB, "attribute certificate is invalid (valid from %T to %T)",
&notBefore, FALSE, &valid_until, FALSE);
return FALSE;
}
- DBG1("attribute certificate is valid until %T", &valid_until, FALSE);
+ DBG1(DBG_LIB, "attribute certificate is valid until %T", &valid_until,
+ FALSE);
lock_authcert_list("verify_x509acert");
aacert = get_authcert(issuer, authKeyID, X509_AA);
@@ -105,17 +106,17 @@ bool ac_verify_cert(certificate_t *cert, bool strict)
if (aacert == NULL)
{
- DBG1("issuer aacert not found");
+ DBG1(DBG_LIB, "issuer aacert not found");
return FALSE;
}
- DBG2("issuer aacert found");
+ DBG2(DBG_LIB, "issuer aacert found");
if (!cert->issued_by(cert, aacert->cert))
{
- DBG1("attribute certificate signature is invalid");
+ DBG1(DBG_LIB, "attribute certificate signature is invalid");
return FALSE;
}
- DBG1("attribute certificate signature is valid");
+ DBG1(DBG_LIB, "attribute certificate signature is valid");
return verify_x509cert(aacert, strict, &valid_until);
}
@@ -175,8 +176,8 @@ bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn,
}
match = conn_attributes->matches(conn_attributes, peer_attributes);
- DBG1("%s: peer with attributes '%s' is %sa member of the groups '%s'",
- conn, peer_attributes->get_string(peer_attributes),
+ DBG1(DBG_LIB, "%s: peer with attributes '%s' is %sa member of the "
+ "groups '%s'", conn, peer_attributes->get_string(peer_attributes),
match ? "" : "not ", conn_attributes->get_string(conn_attributes));
return match;
@@ -191,7 +192,7 @@ void ac_load_certs(void)
struct stat st;
char *file;
- DBG1("loading attribute certificates from '%s'", A_CERT_PATH);
+ DBG1(DBG_LIB, "loading attribute certificates from '%s'", A_CERT_PATH);
enumerator = enumerator_create_directory(A_CERT_PATH);
if (!enumerator)
@@ -212,7 +213,7 @@ void ac_load_certs(void)
BUILD_FROM_FILE, file, BUILD_END);
if (cert)
{
- DBG1(" loaded attribute certificate from '%s'", file);
+ DBG1(DBG_LIB, " loaded attribute certificate from '%s'", file);
ac_add_cert(cert);
}
}
@@ -266,7 +267,7 @@ void ac_list_certs(bool utc)
whack_log(RC_COMMENT, " hserial: %#B", &holderSerial);
}
- groups = ac->get_groups(ac);
+ groups = ac->get_groups(ac);
if (groups)
{
whack_log(RC_COMMENT, " groups: %s", groups->get_string(groups));
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
index edecf14c6..32fd46ef4 100644
--- a/src/pluto/alg_info.c
+++ b/src/pluto/alg_info.c
@@ -139,6 +139,7 @@ static bool is_authenticated_encryption(int ealg_id)
case ESP_AES_GCM_8:
case ESP_AES_GCM_12:
case ESP_AES_GCM_16:
+ case ESP_AES_GMAC:
return TRUE;
}
return FALSE;
@@ -474,7 +475,7 @@ struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
{
- alg_info_ike->ref_cnt = 1;
+ alg_info_ike->ref_cnt = 1;
return alg_info_ike;
}
else
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
index e25e7f6f5..2654774fa 100644
--- a/src/pluto/ca.c
+++ b/src/pluto/ca.c
@@ -293,12 +293,12 @@ void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
struct stat st;
char *file;
- DBG1("loading %s certificates from '%s'", type, path);
+ DBG1(DBG_LIB, "loading %s certificates from '%s'", type, path);
enumerator = enumerator_create_directory(path);
if (!enumerator)
{
- DBG1(" reading directory '%s' failed");
+ DBG1(DBG_LIB, " reading directory '%s' failed", path);
return;
}
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index fece34eec..dd193042a 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -30,6 +30,7 @@
#include <freeswan.h>
#include "kameipsec.h"
+#include <hydra.h>
#include <credentials/certificates/ac.h>
#include <credentials/keys/private_key.h>
@@ -61,6 +62,7 @@
#include "kernel_alg.h"
#include "nat_traversal.h"
#include "virtual.h"
+#include "whack_attribute.h"
static void flush_pending_by_connection(connection_t *c); /* forward */
@@ -104,7 +106,7 @@ bool his_id_was_instantiated(const connection_t *c)
{
identification_t *host;
bool equal;
-
+
host = identification_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_addr);
equal = host->equals(host, c->spd.that.id);
host->destroy(host);
@@ -113,7 +115,7 @@ bool his_id_was_instantiated(const connection_t *c)
else
{
return TRUE;
- }
+ }
}
/**
@@ -369,11 +371,16 @@ void delete_connection(connection_t *c, bool relations)
host_t *vip;
vip = host_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_srcip);
- lib->attributes->release_address(lib->attributes, c->spd.that.pool,
- vip, c->spd.that.id);
+ hydra->attributes->release_address(hydra->attributes, c->spd.that.pool,
+ vip, c->spd.that.id);
vip->destroy(vip);
}
+ if (c->kind != CK_GOING_AWAY)
+ {
+ whack_attr->del_pool(whack_attr, c->name);
+ }
+
/* free internal data */
#ifdef DEBUG
cur_debugging = old_cur_debugging;
@@ -683,7 +690,7 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
}
/* id */
- snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
+ snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
/* [---hop] */
hop[0] = '\0';
@@ -769,7 +776,7 @@ static void load_end_certificate(char *filename, struct end *dst)
cert_t *cert = NULL;
certificate_t *certificate;
bool cached_cert = FALSE;
-
+
/* initialize end certificate */
dst->cert = NULL;
@@ -853,10 +860,11 @@ static void load_end_certificate(char *filename, struct end *dst)
}
static bool extract_end(struct end *dst, const whack_end_t *src,
- const char *which)
+ const char *name, bool is_left)
{
bool same_ca = FALSE;
+ dst->is_left = is_left;
dst->id = identification_create_from_string(src->id);
dst->ca = NULL;
@@ -1117,15 +1125,14 @@ void add_connection(const whack_message_t *wm)
c->tunnel_addr_family = wm->tunnel_addr_family;
c->requested_ca = NULL;
+ same_leftca = extract_end(&c->spd.this, &wm->left, wm->name, TRUE);
+ same_rightca = extract_end(&c->spd.that, &wm->right, wm->name, FALSE);
- same_leftca = extract_end(&c->spd.this, &wm->left, "left");
- same_rightca = extract_end(&c->spd.that, &wm->right, "right");
-
- if (same_rightca)
+ if (same_rightca && c->spd.this.ca)
{
c->spd.that.ca = c->spd.this.ca->clone(c->spd.this.ca);
}
- else if (same_leftca)
+ else if (same_leftca && c->spd.that.ca)
{
c->spd.this.ca = c->spd.that.ca->clone(c->spd.that.ca);
}
@@ -1196,6 +1203,17 @@ void add_connection(const whack_message_t *wm)
(void)orient(c);
+ /* if rightsourceip defines a subnet then create an in-memory pool */
+ if (whack_attr->add_pool(whack_attr, c->name,
+ c->spd.this.is_left ? &wm->right : &wm->left))
+ {
+ c->spd.that.pool = clone_str(c->name);
+ c->spd.that.modecfg = TRUE;
+ c->spd.that.has_client = FALSE;
+ /* reset the host_srcip so that it gets assigned in modecfg */
+ anyaddr(AF_INET, &c->spd.that.host_srcip);
+ }
+
if (c->ikev1)
{
connect_to_host_pair(c);
@@ -1794,7 +1812,7 @@ connection_t *build_outgoing_opportunistic_connection(struct gw_info *gw,
else
{
chunk_t encoding = gw->gw_id->get_encoding(gw->gw_id);
- id_type_t type = gw->gw_id->get_type(gw->gw_id);
+ id_type_t type = gw->gw_id->get_type(gw->gw_id);
ip_address ip_addr;
initaddr(encoding.ptr, encoding.len,
@@ -2758,7 +2776,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
loglog(RC_OPPOFAILURE,
"no suitable connection for opportunism "
- "between %s and %s with %Y as peer",
+ "between %s and %s with %Y as peer",
ocb, pcb, ac->gateways_from_dns->gw_id);
#ifdef KLIPS
@@ -3379,7 +3397,7 @@ connection_t *refine_host_connection(const struct state *st,
id_match_t match_level = peer_id->matches(peer_id, d->spd.that.id);
bool matching_id = match_level > ID_MATCH_NONE;
-
+
bool matching_auth = (d->policy & auth_policy) != LEMPTY;
bool matching_trust = trusted_ca(peer_ca
@@ -3580,7 +3598,7 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
policy_prio_t best_prio = BOTTOM_PRIO;
id_match_t match_level;
int pathlen;
-
+
const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
@@ -3675,7 +3693,8 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
}
else
{
- if (!peer_net_is_host)
+ if (!peer_net_is_host && !(sr->that.modecfg && c->spd.that.modecfg &&
+ subnetisaddr(peer_net, &c->spd.that.host_srcip)))
{
continue;
}
@@ -3843,7 +3862,7 @@ void get_peer_ca_and_groups(connection_t *c,
if (cert && ac_verify_cert(cert, strict_crl_policy))
{
ac_t *ac = (ac_t*)cert;
-
+
*peer_attributes = ac->get_groups(ac);
}
else
diff --git a/src/pluto/connections.h b/src/pluto/connections.h
index ee2e00da6..66aea1541 100644
--- a/src/pluto/connections.h
+++ b/src/pluto/connections.h
@@ -137,6 +137,7 @@ struct end {
host_srcip;
ip_subnet client;
+ bool is_left;
bool key_from_DNS_on_demand;
bool has_client;
bool has_client_wildcard;
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index 6f991fd69..63a37009b 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -392,7 +392,8 @@ static const char *const esp_transform_name[] = {
"AES_GCM_12",
"AES_GCM_16",
"SEED_CBC",
- "CAMELLIA_CBC"
+ "CAMELLIA_CBC",
+ "AES_GMAC"
};
static const char *const esp_transform_name_high[] = {
@@ -404,7 +405,7 @@ enum_names esp_transform_names_high =
{ ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL };
enum_names esp_transform_names =
- { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transform_names_high };
+ { ESP_DES_IV64, ESP_AES_GMAC, esp_transform_name, &esp_transform_names_high };
/* IPCOMP transform values */
@@ -919,12 +920,15 @@ static const char *const oakley_group_name_rfc4753[] = {
};
static const char *const oakley_group_name_rfc5114[] = {
+ "MODP_1024_160",
+ "MODP_2048_224",
+ "MODP_2048_256",
"ECP_192",
"ECP_224"
};
enum_names oakley_group_names_rfc5114 =
- { ECP_192_BIT, ECP_224_BIT,
+ { MODP_1024_160, ECP_224_BIT,
oakley_group_name_rfc5114, NULL };
enum_names oakley_group_names_rfc4753 =
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 8c574ebc5..e9567c07a 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -125,10 +125,10 @@ extern const char sparse_end[];
#define MAX_DIGEST_LEN HASH_SIZE_SHA512
/* RFC 2404 "HMAC-SHA-1-96" section 3 */
-#define HMAC_SHA1_KEY_LEN HASH_SIZE_SHA1
+#define HMAC_SHA1_KEY_LEN HASH_SIZE_SHA1
/* RFC 2403 "HMAC-MD5-96" section 3 */
-#define HMAC_MD5_KEY_LEN HASH_SIZE_MD5
+#define HMAC_MD5_KEY_LEN HASH_SIZE_MD5
#define IKE_UDP_PORT 500
@@ -150,7 +150,7 @@ enum ipsec_authentication_algo {
AH_AES_128_GMAC = 11,
AH_AES_192_GMAC = 12,
AH_AES_256_GMAC = 13,
- AH_SHA2_256_96 = 252
+ AH_SHA2_256_96 = 252
};
extern enum_names ah_transform_names;
@@ -184,6 +184,7 @@ enum ipsec_cipher_algo {
ESP_AES_GCM_16 = 20,
ESP_SEED_CBC = 21,
ESP_CAMELLIA = 22,
+ ESP_AES_GMAC = 23,
ESP_SERPENT = 252,
ESP_TWOFISH = 253
};
diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c
index 2113cecbc..a62e7632d 100644
--- a/src/pluto/crypto.c
+++ b/src/pluto/crypto.c
@@ -237,6 +237,27 @@ static struct dh_desc dh_desc_ecp_521 = {
ke_size: 2*528 / BITS_PER_BYTE
};
+static struct dh_desc dh_desc_modp_1024_160 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_1024_160,
+ algo_next: NULL,
+ ke_size: 1024 / BITS_PER_BYTE
+};
+
+static struct dh_desc dh_desc_modp_2048_224 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_2048_224,
+ algo_next: NULL,
+ ke_size: 2048 / BITS_PER_BYTE
+};
+
+static struct dh_desc dh_desc_modp_2048_256 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_2048_256,
+ algo_next: NULL,
+ ke_size: 2048 / BITS_PER_BYTE
+};
+
static struct dh_desc dh_desc_ecp_192 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_192_BIT,
@@ -370,6 +391,15 @@ bool init_crypto(void)
case ECP_521_BIT:
desc = &dh_desc_ecp_521;
break;
+ case MODP_1024_160:
+ desc = &dh_desc_modp_1024_160;
+ break;
+ case MODP_2048_224:
+ desc = &dh_desc_modp_2048_224;
+ break;
+ case MODP_2048_256:
+ desc = &dh_desc_modp_2048_256;
+ break;
case ECP_192_BIT:
desc = &dh_desc_ecp_192;
break;
@@ -580,9 +610,11 @@ int esp_from_encryption_algorithm(encryption_algorithm_t alg)
return ESP_AES_GCM_16;
case ENCR_CAMELLIA_CBC:
return ESP_CAMELLIA;
+ case ENCR_NULL_AUTH_AES_GMAC:
+ return ESP_AES_GMAC;
case ENCR_SERPENT_CBC:
return ESP_SERPENT;
- case ENCR_TWOFISH_CBC:
+ case ENCR_TWOFISH_CBC:
return ESP_TWOFISH;
default:
return 0;
diff --git a/src/pluto/demux.h b/src/pluto/demux.h
index 4faf6e532..2161bbd02 100644
--- a/src/pluto/demux.h
+++ b/src/pluto/demux.h
@@ -61,6 +61,7 @@ struct msg_digest {
notification_t note; /* reason for failure */
bool dpd; /* peer supports RFC 3706 DPD */
bool openpgp; /* peer supports OpenPGP certificates */
+ bool ms_nt5; /* peer is a windows 2000+ host */
# define PAYLIMIT 40
struct payload_digest
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
index 6172165bd..1d2d13371 100644
--- a/src/pluto/fetch.c
+++ b/src/pluto/fetch.c
@@ -266,10 +266,10 @@ x509crl_t* fetch_crl(char *url)
x509crl_t *crl;
chunk_t blob;
- DBG1(" fetching crl from '%s' ...", url);
+ DBG1(DBG_LIB, " fetching crl from '%s' ...", url);
if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
{
- DBG1("crl fetching failed");
+ DBG1(DBG_LIB, "crl fetching failed");
return FALSE;
}
crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
@@ -277,7 +277,8 @@ x509crl_t* fetch_crl(char *url)
free(blob.ptr);
if (!crl)
{
- DBG1("crl fetched successfully but data coded in unknown format");
+ DBG1(DBG_LIB, "crl fetched successfully but data coded in unknown "
+ "format");
}
return crl;
}
@@ -395,7 +396,7 @@ static void fetch_ocsp_status(ocsp_location_t* location)
chunk_t request = build_ocsp_request(location);
chunk_t response = chunk_empty;
- DBG1(" requesting ocsp status from '%s' ...", location->uri);
+ DBG1(DBG_LIB, " requesting ocsp status from '%s' ...", location->uri);
if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
FETCH_REQUEST_DATA, request,
FETCH_REQUEST_TYPE, "application/ocsp-request",
@@ -405,7 +406,7 @@ static void fetch_ocsp_status(ocsp_location_t* location)
}
else
{
- DBG1("ocsp request to %s failed", location->uri);
+ DBG1(DBG_LIB, "ocsp request to %s failed", location->uri);
}
free(request.ptr);
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
index 1f8917d79..34c42e294 100644
--- a/src/pluto/ipsec_doi.c
+++ b/src/pluto/ipsec_doi.c
@@ -702,6 +702,8 @@ void accept_delete(struct state *st, struct msg_digest *md,
struct payload_digest *p)
{
struct isakmp_delete *d = &(p->payload.delete);
+ identification_t *this_id, *that_id;
+ ip_address peer_addr;
size_t sizespi;
int i;
@@ -759,6 +761,15 @@ void accept_delete(struct state *st, struct msg_digest *md,
return;
}
+ if (d->isad_protoid == PROTO_ISAKMP)
+ {
+ struct end *this = &st->st_connection->spd.this;
+ struct end *that = &st->st_connection->spd.that;
+ this_id = this->id->clone(this->id);
+ that_id = that->id->clone(that->id);
+ peer_addr = st->st_connection->spd.that.host_addr;
+ }
+
for (i = 0; i < d->isad_nospi; i++)
{
u_char *spi = p->pbs.cur + (i * sizespi);
@@ -770,7 +781,7 @@ void accept_delete(struct state *st, struct msg_digest *md,
*/
struct state *dst = find_state(spi /*iCookie*/
, spi+COOKIE_SIZE /*rCookie*/
- , &st->st_connection->spd.that.host_addr
+ , &peer_addr
, MAINMODE_MSGID);
if (dst == NULL)
@@ -778,7 +789,8 @@ void accept_delete(struct state *st, struct msg_digest *md,
loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
"ISAKMP SA not found (maybe expired)");
}
- else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL))
+ else if (! this_id->equals(this_id, dst->st_connection->spd.this.id) ||
+ ! that_id->equals(that_id, dst->st_connection->spd.that.id))
{
/* we've not authenticated the relevant identities */
loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
@@ -876,6 +888,12 @@ void accept_delete(struct state *st, struct msg_digest *md,
}
}
}
+
+ if (d->isad_protoid == PROTO_ISAKMP)
+ {
+ this_id->destroy(this_id);
+ that_id->destroy(that_id);
+ }
}
/* The whole message must be a multiple of 4 octets.
@@ -2753,6 +2771,7 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid,
case ESP_AES_GCM_12:
case ESP_AES_GCM_16:
case ESP_AES_CTR:
+ case ESP_AES_GMAC:
needed_len += 4;
break;
default:
@@ -3620,7 +3639,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
if (send_cert)
{
bool success;
- chunk_t cert_encoding;
+ chunk_t cert_encoding;
pb_stream cert_pbs;
struct isakmp_cert cert_hd;
@@ -3634,7 +3653,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
cert_encoding = mycert->cert->get_encoding(mycert->cert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
- if (!success)
+ if (!success)
{
return STF_INTERNAL_ERROR;
}
@@ -4076,7 +4095,7 @@ main_inI3_outR3_tail(struct msg_digest *md
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
if (!success)
- {
+ {
return STF_INTERNAL_ERROR;
}
close_output_pbs(&cert_pbs);
@@ -4871,6 +4890,21 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
*/
p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
, his_net, c->spd.that.id);
+
+ /* inherit any virtual IP assigned by a Mode Config exchange */
+ if (p->spd.that.modecfg && c->spd.that.modecfg &&
+ subnetisaddr(his_net, &c->spd.that.host_srcip))
+ {
+ char srcip[ADDRTOT_BUF];
+
+ DBG(DBG_CONTROL,
+ addrtot(&c->spd.that.host_srcip, 0, srcip, sizeof(srcip));
+ DBG_log("inheriting virtual IP source address %s from ModeCfg", srcip)
+ )
+ p->spd.that.host_srcip = c->spd.that.host_srcip;
+ p->spd.that.client = c->spd.that.client;
+ p->spd.that.has_client = TRUE;
+ }
}
}
#ifdef DEBUG
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index fe4655d3f..ee22fb55e 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -1993,6 +1993,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
case ESP_AES_GCM_12:
case ESP_AES_GCM_16:
case ESP_AES_CTR:
+ case ESP_AES_GMAC:
key_len += 4;
break;
default:
diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c
index bf67315e6..7c2855edc 100644
--- a/src/pluto/kernel_alg.c
+++ b/src/pluto/kernel_alg.c
@@ -395,6 +395,10 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
kernel_alg_add(satype, supp_exttype, &alg);
}
}
+
+ /* also register AES_GMAC */
+ alg.sadb_alg_id = SADB_X_EALG_NULL_AES_GMAC;
+ kernel_alg_add(satype, supp_exttype, &alg);
}
/* if SHA2_256 is registered then also register SHA2_256_96 */
if (satype == SADB_SATYPE_ESP &&
diff --git a/src/pluto/kernel_netlink.c b/src/pluto/kernel_netlink.c
index 289714b50..75d0c98d3 100644
--- a/src/pluto/kernel_netlink.c
+++ b/src/pluto/kernel_netlink.c
@@ -112,6 +112,7 @@ static sparse_names ealg_list = {
{ SADB_X_EALG_AES_GCM_ICV8, "rfc4106(gcm(aes))" },
{ SADB_X_EALG_AES_GCM_ICV12, "rfc4106(gcm(aes))" },
{ SADB_X_EALG_AES_GCM_ICV16, "rfc4106(gcm(aes))" },
+ { SADB_X_EALG_NULL_AES_GMAC, "rfc4543(gcm(aes))" },
{ SADB_X_EALG_CAMELLIACBC, "cbc(camellia)" },
{ SADB_X_EALG_SERPENTCBC, "serpent" },
{ SADB_X_EALG_TWOFISHCBC, "twofish" },
@@ -687,6 +688,7 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
break;
case SADB_X_EALG_AES_CCM_ICV16:
case SADB_X_EALG_AES_GCM_ICV16:
+ case SADB_X_EALG_NULL_AES_GMAC:
icv_size += 32;
/* FALL */
case SADB_X_EALG_AES_CCM_ICV12:
diff --git a/src/pluto/lex.c b/src/pluto/lex.c
index f48d24a54..d5ebdaba9 100644
--- a/src/pluto/lex.c
+++ b/src/pluto/lex.c
@@ -205,7 +205,7 @@ flushline(const char *m)
{
if (m != NULL)
loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m);
- do ; while (shift());
+ do {} while (shift());
return FALSE;
}
}
diff --git a/src/pluto/log.c b/src/pluto/log.c
index 2f3536ff3..444ac2220 100644
--- a/src/pluto/log.c
+++ b/src/pluto/log.c
@@ -40,7 +40,8 @@
#include "connections.h"
#include "myid.h"
#include "kernel.h"
-#include "whack.h" /* needs connections.h */
+#include "whack.h"
+#include "whack_attribute.h"
#include "timer.h"
/* close one per-peer log */
@@ -85,7 +86,7 @@ u_int16_t cur_from_port; /* host order */
/**
* pluto dbg function for libstrongswan
*/
-static void pluto_dbg(int level, char *fmt, ...)
+static void pluto_dbg(debug_t group, level_t level, char *fmt, ...)
{
int priority = LOG_INFO;
int debug_level;
@@ -856,6 +857,7 @@ void show_status(bool all, const char *name)
show_myid_status();
show_loaded_plugins();
show_debug_status();
+ show_pools(name);
whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
}
show_connections_status(all, name);
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 03ec7f41f..0c4f2bd6b 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -26,6 +26,7 @@
#include <freeswan.h>
#include <library.h>
+#include <hydra.h>
#include <attributes/attributes.h>
#include <crypto/prfs/prf.h>
@@ -119,7 +120,7 @@ static void init_internal_addr(internal_addr_t *ia)
static void get_internal_addr(connection_t *c, host_t *requested_vip,
internal_addr_t *ia)
{
- int i, dns_idx = 0, nbns_idx = 0;
+ int dns_idx = 0, nbns_idx = 0;
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
@@ -129,13 +130,13 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
{
if (c->spd.that.pool)
{
- vip = lib->attributes->acquire_address(lib->attributes,
+ vip = hydra->attributes->acquire_address(hydra->attributes,
c->spd.that.pool, c->spd.that.id,
requested_vip);
if (vip)
{
chunk_t addr = vip->get_address(vip);
-
+
plog("assigning virtual IP %H to peer", vip);
initaddr(addr.ptr, addr.len, vip->get_family(vip), &ia->ipaddr);
@@ -150,7 +151,7 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
{
ia->ipaddr = c->spd.that.host_srcip;
vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr);
- plog("assigning virtual IP %H to peer", vip);
+ plog("assigning virtual IP %H to peer", vip);
}
if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
@@ -164,67 +165,15 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
| LELEM(INTERNAL_IP4_NETMASK);
}
- /* assign DNS servers from strongswan.conf */
- for (i = 1; i <= DNS_SERVER_MAX; i++)
- {
- char dns_key[16], *dns_str;
-
- snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i);
- dns_str = lib->settings->get_str(lib->settings, dns_key, NULL);
- if (dns_str)
- {
- err_t ugh;
- sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET;
-
- ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]);
- if (ugh)
- {
- plog("error in DNS server address: %s", ugh);
- continue;
- }
- plog("assigning DNS server %s to peer", dns_str);
-
- /* differentiate between IP4 and IP6 in modecfg_build_msg() */
- ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
- dns_idx++;
- }
- }
-
- /* assign NBNS servers from strongswan.conf */
- for (i = 1; i <= NBNS_SERVER_MAX; i++)
- {
- char nbns_key[16], *nbns_str;
-
- snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i);
- nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL);
- if (nbns_str)
- {
- err_t ugh;
- sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET;
-
- ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]);
- if (ugh)
- {
- plog("error in NBNS server address: %s", ugh);
- continue;
- }
- plog("assigning NBNS server %s to peer", nbns_str);
-
- /* differentiate between IP4 and IP6 in modecfg_build_msg() */
- ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
- nbns_idx++;
- }
- }
-
/* assign attributes from registered providers */
- enumerator = lib->attributes->create_responder_enumerator(lib->attributes,
+ enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes,
c->spd.that.id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
err_t ugh;
host_t *server;
sa_family_t family = AF_INET;
-
+
switch (type)
{
case INTERNAL_IP6_DNS:
@@ -257,7 +206,7 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
/* fallthrough */
case INTERNAL_IP4_NBNS:
if (nbns_idx >= NBNS_SERVER_MAX)
- {
+ {
plog("exceeded the maximum number of %d NBNS servers",
NBNS_SERVER_MAX);
break;
@@ -279,7 +228,7 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
default:
break;
- }
+ }
}
enumerator->destroy(enumerator);
DESTROY_IF(vip);
diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c
index 733dd2623..b24ef1a8c 100644
--- a/src/pluto/pkcs7.c
+++ b/src/pluto/pkcs7.c
@@ -146,7 +146,7 @@ bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
if (cInfo->type < OID_PKCS7_DATA
|| cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
{
- DBG1("unknown pkcs7 content type");
+ DBG1(DBG_LIB, "unknown pkcs7 content type");
goto end;
}
}
@@ -187,7 +187,7 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
}
if (cInfo.type != OID_PKCS7_SIGNED_DATA)
{
- DBG1("pkcs7 content type is not signedData");
+ DBG1(DBG_LIB, "pkcs7 content type is not signedData");
return FALSE;
}
@@ -202,7 +202,7 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
{
case PKCS7_SIGNED_VERSION:
version = object.len ? (int)*object.ptr : 0;
- DBG2(" v%d", version);
+ DBG2(DBG_LIB, " v%d", version);
break;
case PKCS7_DIGEST_ALG:
digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
@@ -217,7 +217,7 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
{
certificate_t *cert;
- DBG2(" parsing pkcs7-wrapped certificate");
+ DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
@@ -230,17 +230,17 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
break;
case PKCS7_SIGNER_INFO:
signerInfos++;
- DBG2(" signer #%d", signerInfos);
+ DBG2(DBG_LIB, " signer #%d", signerInfos);
break;
case PKCS7_SIGNER_INFO_VERSION:
version = object.len ? (int)*object.ptr : 0;
- DBG2(" v%d", version);
+ DBG2(DBG_LIB, " v%d", version);
break;
case PKCS7_SIGNED_ISSUER:
{
identification_t *issuer = identification_create_from_encoding(
ID_DER_ASN1_DN, object);
- DBG2(" \"%Y\"", issuer);
+ DBG2(DBG_LIB, " \"%Y\"", issuer);
issuer->destroy(issuer);
break;
}
@@ -277,27 +277,27 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
scheme = signature_scheme_from_oid(digest_alg);
if (scheme == SIGN_UNKNOWN)
{
- DBG1("unsupported signature scheme");
+ DBG1(DBG_LIB, "unsupported signature scheme");
return FALSE;
}
if (signerInfos == 0)
{
- DBG1("no signerInfo object found");
+ DBG1(DBG_LIB, "no signerInfo object found");
return FALSE;
}
else if (signerInfos > 1)
{
- DBG1("more than one signerInfo object found");
+ DBG1(DBG_LIB, "more than one signerInfo object found");
return FALSE;
}
if (attributes->ptr == NULL)
{
- DBG1("no authenticatedAttributes object found");
+ DBG1(DBG_LIB, "no authenticatedAttributes object found");
return FALSE;
}
if (enc_alg != OID_RSA_ENCRYPTION)
{
- DBG1("only RSA digest encryption supported");
+ DBG1(DBG_LIB, "only RSA digest encryption supported");
return FALSE;
}
@@ -305,16 +305,16 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
key = cacert->get_public_key(cacert);
if (key == NULL)
{
- DBG1("no public key found in CA certificate");
+ DBG1(DBG_LIB, "no public key found in CA certificate");
return FALSE;
}
if (key->verify(key, scheme, *attributes, encrypted_digest))
{
- DBG2("signature is valid");
+ DBG2(DBG_LIB, "signature is valid");
}
else
{
- DBG1("invalid signature");
+ DBG1(DBG_LIB, "invalid signature");
success = FALSE;
}
key->destroy(key);
@@ -352,7 +352,7 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
}
if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
{
- DBG1("pkcs7 content type is not envelopedData");
+ DBG1(DBG_LIB, "pkcs7 content type is not envelopedData");
goto failed;
}
@@ -367,19 +367,19 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
{
case PKCS7_ENVELOPED_VERSION:
version = object.len ? (int)*object.ptr : 0;
- DBG2(" v%d", version);
+ DBG2(DBG_LIB, " v%d", version);
if (version != 0)
{
- DBG1("envelopedData version is not 0");
+ DBG1(DBG_LIB, "envelopedData version is not 0");
goto end;
}
break;
case PKCS7_RECIPIENT_INFO_VERSION:
version = object.len ? (int)*object.ptr : 0;
- DBG2(" v%d", version);
+ DBG2(DBG_LIB, " v%d", version);
if (version != 0)
{
- DBG1("recipient info version is not 0");
+ DBG1(DBG_LIB, "recipient info version is not 0");
goto end;
}
break;
@@ -387,14 +387,14 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
{
identification_t *issuer = identification_create_from_encoding(
ID_DER_ASN1_DN, object);
- DBG2(" \"%Y\"", issuer);
+ DBG2(DBG_LIB, " \"%Y\"", issuer);
issuer->destroy(issuer);
break;
}
case PKCS7_SERIAL_NUMBER:
if (!chunk_equals(serialNumber, object))
{
- DBG1("serial numbers do not match");
+ DBG1(DBG_LIB, "serial numbers do not match");
goto end;
}
break;
@@ -402,22 +402,22 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
if (enc_alg != OID_RSA_ENCRYPTION)
{
- DBG1("only rsa encryption supported");
+ DBG1(DBG_LIB, "only rsa encryption supported");
goto end;
}
break;
case PKCS7_ENCRYPTED_KEY:
if (!key->decrypt(key, object, &symmetric_key))
{
- DBG1("symmetric key could not be decrypted with rsa");
+ DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
goto end;
}
- DBG4("symmetric key %B", &symmetric_key);
+ DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
break;
case PKCS7_CONTENT_TYPE:
if (asn1_known_oid(object) != OID_PKCS7_DATA)
{
- DBG1("encrypted content not of type pkcs7 data");
+ DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
goto end;
}
break;
@@ -426,12 +426,12 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
if (content_enc_alg == OID_UNKNOWN)
{
- DBG1("unknown content encryption algorithm");
+ DBG1(DBG_LIB, "unknown content encryption algorithm");
goto end;
}
if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
{
- DBG1("IV could not be parsed");
+ DBG1(DBG_LIB, "IV could not be parsed");
goto end;
}
break;
@@ -459,28 +459,28 @@ end:
alg = encryption_algorithm_from_oid(content_enc_alg, &key_size);
if (alg == ENCR_UNDEFINED)
{
- DBG1("unsupported content encryption algorithm");
+ DBG1(DBG_LIB, "unsupported content encryption algorithm");
goto failed;
}
crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
if (crypter == NULL)
{
- DBG1("crypter %N not available", encryption_algorithm_names, alg);
+ DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg);
goto failed;
}
if (symmetric_key.len != crypter->get_key_size(crypter))
{
- DBG1("symmetric key length %d is wrong", symmetric_key.len);
+ DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len);
goto failed;
}
if (iv.len != crypter->get_block_size(crypter))
{
- DBG1("IV length %d is wrong", iv.len);
+ DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
goto failed;
}
crypter->set_key(crypter, symmetric_key);
crypter->decrypt(crypter, encrypted_content, iv, data);
- DBG4("decrypted content with padding: %B", data);
+ DBG4(DBG_LIB, "decrypted content with padding: %B", data);
}
/* remove the padding */
@@ -491,7 +491,7 @@ end:
if (padding > data->len)
{
- DBG1("padding greater than data length");
+ DBG1(DBG_LIB, "padding greater than data length");
goto failed;
}
data->len -= padding;
@@ -500,7 +500,7 @@ end:
{
if (*pos-- != pattern)
{
- DBG1("wrong padding pattern");
+ DBG1(DBG_LIB, "wrong padding pattern");
goto failed;
}
}
@@ -631,7 +631,7 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
, asn1_wrap(ASN1_SET, "m", signerInfo));
cInfo = pkcs7_build_contentInfo(&signedData);
- DBG3("signedData %B", &cInfo);
+ DBG3(DBG_LIB, "signedData %B", &cInfo);
free(pkcs7Data.content.ptr);
free(signedData.content.ptr);
@@ -653,7 +653,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
alg_key_size/BITS_PER_BYTE);
if (crypter == NULL)
{
- DBG1("crypter for %N not available", encryption_algorithm_names, alg);
+ DBG1(DBG_LIB, "crypter for %N not available", encryption_algorithm_names, alg);
return chunk_empty;
}
@@ -663,12 +663,12 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey);
- DBG4("symmetric encryption key %B", &symmetricKey);
+ DBG4(DBG_LIB, "symmetric encryption key %B", &symmetricKey);
rng->destroy(rng);
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
rng->allocate_bytes(rng, crypter->get_block_size(crypter), &iv);
- DBG4("initialization vector: %B", &iv);
+ DBG4(DBG_LIB, "initialization vector: %B", &iv);
rng->destroy(rng);
}
@@ -680,7 +680,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
in.len = data.len + padding;
in.ptr = malloc(in.len);
- DBG2("padding %u bytes of data to multiple block size of %u bytes",
+ DBG2(DBG_LIB, "padding %u bytes of data to multiple block size of %u bytes",
data.len, in.len);
/* copy data */
@@ -688,14 +688,14 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
/* append padding */
memset(in.ptr + data.len, padding, padding);
}
- DBG3("padded unencrypted data %B", &in);
+ DBG3(DBG_LIB, "padded unencrypted data %B", &in);
/* symmetric encryption of data object */
crypter->set_key(crypter, symmetricKey);
crypter->encrypt(crypter, in, iv, &out);
crypter->destroy(crypter);
chunk_clear(&in);
- DBG3("encrypted data %B", &out);
+ DBG3(DBG_LIB, "encrypted data %B", &out);
/* protect symmetric key by public key encryption */
{
@@ -703,7 +703,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
if (key == NULL)
{
- DBG1("public key not found in encryption certificate");
+ DBG1(DBG_LIB, "public key not found in encryption certificate");
chunk_clear(&symmetricKey);
chunk_free(&iv);
chunk_free(&out);
@@ -744,7 +744,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
, encryptedContentInfo);
cInfo = pkcs7_build_contentInfo(&envelopedData);
- DBG3("envelopedData %B", &cInfo);
+ DBG3(DBG_LIB, "envelopedData %B", &cInfo);
chunk_free(&envelopedData.content);
chunk_free(&iv);
diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c
index 8b922df8c..aa04594bc 100644
--- a/src/pluto/plutomain.c
+++ b/src/pluto/plutomain.c
@@ -38,6 +38,7 @@
#include <freeswan.h>
+#include <hydra.h>
#include <library.h>
#include <debug.h>
#include <utils/enumerator.h>
@@ -74,6 +75,7 @@
#include "timer.h"
#include "vendor.h"
#include "builder.h"
+#include "whack_attribute.h"
static void usage(const char *mess)
{
@@ -242,7 +244,7 @@ static void print_plugins()
len += snprintf(&buf[len], BUF_LEN-len, "%s ", plugin);
}
enumerator->destroy(enumerator);
- DBG1("loaded plugins: %s", buf);
+ DBG1(DBG_DMN, "loaded plugins: %s", buf);
}
int main(int argc, char **argv)
@@ -273,6 +275,12 @@ int main(int argc, char **argv)
library_deinit();
exit(SS_RC_DAEMON_INTEGRITY);
}
+ if (!libhydra_init("pluto"))
+ {
+ libhydra_deinit();
+ library_deinit();
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
options = options_create();
/* handle arguments */
@@ -648,6 +656,7 @@ int main(int argc, char **argv)
{
plog("integrity tests enabled:");
plog("lib 'libstrongswan': passed file and segment integrity tests");
+ plog("lib 'libhydra': passed file and segment integrity tests");
plog("daemon 'pluto': passed file integrity test");
}
@@ -676,6 +685,7 @@ int main(int argc, char **argv)
init_myid();
fetch_initialize();
ac_initialize();
+ whack_attribute_initialize();
/* drop unneeded capabilities and change UID/GID */
prctl(PR_SET_KEEPCAPS, 1);
@@ -750,6 +760,7 @@ void exit_pluto(int status)
free_preshared_secrets();
free_remembered_public_keys();
delete_every_connection();
+ whack_attribute_finalize(); /* free in-memory pools */
fetch_finalize(); /* stop fetching thread */
free_crl_fetch(); /* free chain of crl fetch requests */
free_ocsp_fetch(); /* free chain of ocsp fetch requests */
@@ -770,6 +781,8 @@ void exit_pluto(int status)
free_builder();
delete_lock();
options->destroy(options);
+ lib->plugins->unload(lib->plugins);
+ libhydra_deinit();
library_deinit();
close_log();
exit(status);
diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c
index 826a1aa6e..bf5ccb10c 100644
--- a/src/pluto/rcv_whack.c
+++ b/src/pluto/rcv_whack.c
@@ -57,6 +57,7 @@
#include "myid.h"
#include "kernel_alg.h"
#include "ike_alg.h"
+#include "whack_attribute.h"
/* helper variables and function to decode strings from whack message */
@@ -326,6 +327,8 @@ void whack_handle(int whackctlfd)
|| !unpack_str(&msg.ike) /* string 24 */
|| !unpack_str(&msg.esp) /* string 25 */
|| !unpack_str(&msg.sc_data) /* string 26 */
+ || !unpack_str(&msg.whack_lease_ip) /* string 27 */
+ || !unpack_str(&msg.whack_lease_id) /* string 28 */
|| str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
{
ugh = "message from whack contains bad string";
@@ -376,7 +379,9 @@ void whack_handle(int whackctlfd)
}
if (msg.whack_myid)
+ {
set_myid(MYID_SPECIFIED, msg.myid);
+ }
/* Deleting combined with adding a connection works as replace.
* To make this more useful, in only this combination,
@@ -385,9 +390,13 @@ void whack_handle(int whackctlfd)
if (msg.whack_delete)
{
if (msg.whack_ca)
+ {
find_ca_info_by_name(msg.name, TRUE);
+ }
else
+ {
delete_connections_by_name(msg.name, !msg.whack_connection);
+ }
}
if (msg.whack_deletestate)
@@ -406,13 +415,19 @@ void whack_handle(int whackctlfd)
}
if (msg.whack_crash)
+ {
delete_states_by_peer(&msg.whack_crash_peer);
+ }
if (msg.whack_connection)
+ {
add_connection(&msg);
+ }
if (msg.whack_ca && msg.cacert != NULL)
+ {
add_ca_info(&msg);
+ }
/* process "listen" before any operation that could require it */
if (msg.whack_listen)
@@ -469,7 +484,12 @@ void whack_handle(int whackctlfd)
free_ocsp_cache();
}
- if (msg.whack_list & LIST_PUBKEYS)
+ if (msg.whack_leases)
+ {
+ list_leases(msg.name, msg.whack_lease_ip, msg.whack_lease_id);
+ }
+
+ if (msg.whack_list & LIST_PUBKEYS)
{
list_public_keys(msg.whack_utc);
}
@@ -552,12 +572,18 @@ void whack_handle(int whackctlfd)
{
set_cur_connection(c);
if (!oriented(*c))
+ {
whack_log(RC_ORIENT
, "we have no ipsecN interface for either end of this connection");
+ }
else if (c->policy & POLICY_GROUP)
+ {
route_group(c);
+ }
else if (!trap_connection(c))
+ {
whack_log(RC_ROUTE, "could not route");
+ }
reset_cur_connection();
}
}
@@ -584,14 +610,22 @@ void whack_handle(int whackctlfd)
for (sr = &c->spd; sr != NULL; sr = sr->next)
{
if (sr->routing >= RT_ROUTED_TUNNEL)
+ {
fail++;
+ }
}
if (fail > 0)
+ {
whack_log(RC_RTBUSY, "cannot unroute: route busy");
+ }
else if (c->policy & POLICY_GROUP)
+ {
unroute_group(c);
+ }
else
+ {
unroute_connection(c);
+ }
reset_cur_connection();
}
}
@@ -618,11 +652,15 @@ void whack_handle(int whackctlfd)
if (msg.whack_oppo_initiate)
{
if (!listening)
+ {
whack_log(RC_DEAF, "need --listen before opportunistic initiation");
+ }
else
+ {
initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
, FALSE
, msg.whack_async? NULL_FD : dup_any(whackfd));
+ }
}
if (msg.whack_terminate)
@@ -639,7 +677,9 @@ void whack_handle(int whackctlfd)
}
if (msg.whack_status)
+ {
show_status(msg.whack_statusall, msg.name);
+ }
if (msg.whack_shutdown)
{
@@ -650,10 +690,14 @@ void whack_handle(int whackctlfd)
if (msg.whack_sc_op != SC_OP_NONE)
{
if (pkcs11_proxy)
+ {
scx_op_via_whack(msg.sc_data, msg.inbase, msg.outbase
, msg.whack_sc_op, msg.keyid, whackfd);
+ }
else
+ {
plog("pkcs11 access to smartcard not allowed (set pkcs11proxy=yes)");
+ }
}
whack_log_fd = NULL_FD;
diff --git a/src/pluto/timer.c b/src/pluto/timer.c
index 74806a40c..b112d67f6 100644
--- a/src/pluto/timer.c
+++ b/src/pluto/timer.c
@@ -48,7 +48,7 @@ time_t now(void)
{
static time_t delta = 0
, last_time = 0;
- time_t n = time((time_t)NULL);
+ time_t n = time(NULL);
passert(n != (time_t)-1);
if (last_time > n)
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
index 7d3c96c87..99cfc5734 100644
--- a/src/pluto/vendor.c
+++ b/src/pluto/vendor.c
@@ -198,6 +198,7 @@ static struct vid_struct _vid_tab[] = {
* strongSwan
*/
DEC_MD5_VID(STRONGSWAN, "strongSwan")
+
DEC_MD5_VID(STRONGSWAN_4_3_5, "strongSwan 4.3.5")
DEC_MD5_VID(STRONGSWAN_4_3_4, "strongSwan 4.3.4")
DEC_MD5_VID(STRONGSWAN_4_3_3, "strongSwan 4.3.3")
@@ -234,14 +235,6 @@ static struct vid_struct _vid_tab[] = {
DEC_MD5_VID(STRONGSWAN_4_1_2, "strongSwan 4.1.2")
DEC_MD5_VID(STRONGSWAN_4_1_1, "strongSwan 4.1.1")
DEC_MD5_VID(STRONGSWAN_4_1_0, "strongSwan 4.1.0")
- DEC_MD5_VID(STRONGSWAN_4_0_7, "strongSwan 4.0.7")
- DEC_MD5_VID(STRONGSWAN_4_0_6, "strongSwan 4.0.6")
- DEC_MD5_VID(STRONGSWAN_4_0_5, "strongSwan 4.0.5")
- DEC_MD5_VID(STRONGSWAN_4_0_4, "strongSwan 4.0.4")
- DEC_MD5_VID(STRONGSWAN_4_0_3, "strongSwan 4.0.3")
- DEC_MD5_VID(STRONGSWAN_4_0_2, "strongSwan 4.0.2")
- DEC_MD5_VID(STRONGSWAN_4_0_1, "strongSwan 4.0.1")
- DEC_MD5_VID(STRONGSWAN_4_0_0, "strongSwan 4.0.0")
DEC_MD5_VID(STRONGSWAN_2_8_11,"strongSwan 2.8.11")
DEC_MD5_VID(STRONGSWAN_2_8_10,"strongSwan 2.8.10")
@@ -255,34 +248,6 @@ static struct vid_struct _vid_tab[] = {
DEC_MD5_VID(STRONGSWAN_2_8_2, "strongSwan 2.8.2")
DEC_MD5_VID(STRONGSWAN_2_8_1, "strongSwan 2.8.1")
DEC_MD5_VID(STRONGSWAN_2_8_0, "strongSwan 2.8.0")
- DEC_MD5_VID(STRONGSWAN_2_7_3, "strongSwan 2.7.3")
- DEC_MD5_VID(STRONGSWAN_2_7_2, "strongSwan 2.7.2")
- DEC_MD5_VID(STRONGSWAN_2_7_1, "strongSwan 2.7.1")
- DEC_MD5_VID(STRONGSWAN_2_7_0, "strongSwan 2.7.0")
- DEC_MD5_VID(STRONGSWAN_2_6_4, "strongSwan 2.6.4")
- DEC_MD5_VID(STRONGSWAN_2_6_3, "strongSwan 2.6.3")
- DEC_MD5_VID(STRONGSWAN_2_6_2, "strongSwan 2.6.2")
- DEC_MD5_VID(STRONGSWAN_2_6_1, "strongSwan 2.6.1")
- DEC_MD5_VID(STRONGSWAN_2_6_0, "strongSwan 2.6.0")
- DEC_MD5_VID(STRONGSWAN_2_5_7, "strongSwan 2.5.7")
- DEC_MD5_VID(STRONGSWAN_2_5_6, "strongSwan 2.5.6")
- DEC_MD5_VID(STRONGSWAN_2_5_5, "strongSwan 2.5.5")
- DEC_MD5_VID(STRONGSWAN_2_5_4, "strongSwan 2.5.4")
- DEC_MD5_VID(STRONGSWAN_2_5_3, "strongSwan 2.5.3")
- DEC_MD5_VID(STRONGSWAN_2_5_2, "strongSwan 2.5.2")
- DEC_MD5_VID(STRONGSWAN_2_5_1, "strongSwan 2.5.1")
- DEC_MD5_VID(STRONGSWAN_2_5_0, "strongSwan 2.5.0")
- DEC_MD5_VID(STRONGSWAN_2_4_4, "strongSwan 2.4.4")
- DEC_MD5_VID(STRONGSWAN_2_4_3, "strongSwan 2.4.3")
- DEC_MD5_VID(STRONGSWAN_2_4_2, "strongSwan 2.4.2")
- DEC_MD5_VID(STRONGSWAN_2_4_1, "strongSwan 2.4.1")
- DEC_MD5_VID(STRONGSWAN_2_4_0, "strongSwan 2.4.0")
- DEC_MD5_VID(STRONGSWAN_2_3_2, "strongSwan 2.3.2")
- DEC_MD5_VID(STRONGSWAN_2_3_1, "strongSwan 2.3.1")
- DEC_MD5_VID(STRONGSWAN_2_3_0, "strongSwan 2.3.0")
- DEC_MD5_VID(STRONGSWAN_2_2_2, "strongSwan 2.2.2")
- DEC_MD5_VID(STRONGSWAN_2_2_1, "strongSwan 2.2.1")
- DEC_MD5_VID(STRONGSWAN_2_2_0, "strongSwan 2.2.0")
/* NAT-Traversal */
@@ -375,51 +340,63 @@ static void handle_known_vendorid (struct msg_digest *md, const char *vidstr,
bool vid_useful = FALSE;
size_t i, j;
- switch (vid->id) {
- /* Remote side supports OpenPGP certificates */
- case VID_OPENPGP:
- md->openpgp = TRUE;
- vid_useful = TRUE;
- break;
+ switch (vid->id)
+ {
+ /* Remote side is a strongSwan host */
+ case VID_STRONGSWAN:
+ vid_useful = TRUE;
+ break;
+
+ /* Remote side supports OpenPGP certificates */
+ case VID_OPENPGP:
+ md->openpgp = TRUE;
+ vid_useful = TRUE;
+ break;
- /*
- * Use most recent supported NAT-Traversal method and ignore the
- * other ones (implementations will send all supported methods but
- * only one will be used)
- *
- * Note: most recent == higher id in vendor.h
- */
- case VID_NATT_IETF_00:
- if (!nat_traversal_support_non_ike)
+ /* Remote side is a Windows 2000+ host */
+ case VID_MS_NT5:
+ md->ms_nt5 = TRUE;
+ vid_useful = TRUE;
break;
- if ((nat_traversal_enabled) && (!md->nat_traversal_vid))
- {
- md->nat_traversal_vid = vid->id;
+
+ /*
+ * Use most recent supported NAT-Traversal method and ignore the
+ * other ones (implementations will send all supported methods but
+ * only one will be used)
+ *
+ * Note: most recent == higher id in vendor.h
+ */
+ case VID_NATT_IETF_00:
+ if (!nat_traversal_support_non_ike)
+ break;
+ if ((nat_traversal_enabled) && (!md->nat_traversal_vid))
+ {
+ md->nat_traversal_vid = vid->id;
+ vid_useful = TRUE;
+ }
+ break;
+ case VID_NATT_IETF_02:
+ case VID_NATT_IETF_02_N:
+ case VID_NATT_IETF_03:
+ case VID_NATT_RFC:
+ if (nat_traversal_support_port_floating
+ && md->nat_traversal_vid < vid->id)
+ {
+ md->nat_traversal_vid = vid->id;
+ vid_useful = TRUE;
+ }
+ break;
+
+ /* Remote side would like to do DPD with us on this connection */
+ case VID_MISC_DPD:
+ md->dpd = TRUE;
vid_useful = TRUE;
- }
- break;
- case VID_NATT_IETF_02:
- case VID_NATT_IETF_02_N:
- case VID_NATT_IETF_03:
- case VID_NATT_RFC:
- if (nat_traversal_support_port_floating
- && md->nat_traversal_vid < vid->id)
- {
- md->nat_traversal_vid = vid->id;
+ break;
+ case VID_MISC_XAUTH:
vid_useful = TRUE;
- }
- break;
-
- /* Remote side would like to do DPD with us on this connection */
- case VID_MISC_DPD:
- md->dpd = TRUE;
- vid_useful = TRUE;
- break;
- case VID_MISC_XAUTH:
- vid_useful = TRUE;
- break;
- default:
- break;
+ break;
+ default:
+ break;
}
if (vid->flags & VID_SUBSTRING_DUMPHEXA)
diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h
index 3df1a8196..ac6b0d420 100644
--- a/src/pluto/vendor.h
+++ b/src/pluto/vendor.h
@@ -53,56 +53,21 @@ enum known_vendorid {
VID_VISTA_AUTHIP2 = 34,
VID_VISTA_AUTHIP3 = 35,
- VID_STRONGSWAN = 37,
- VID_STRONGSWAN_2_2_0 = 38,
- VID_STRONGSWAN_2_2_1 = 39,
- VID_STRONGSWAN_2_2_2 = 40,
- VID_STRONGSWAN_2_3_0 = 41,
- VID_STRONGSWAN_2_3_1 = 42,
- VID_STRONGSWAN_2_3_2 = 43,
- VID_STRONGSWAN_2_4_0 = 44,
- VID_STRONGSWAN_2_4_1 = 45,
- VID_STRONGSWAN_2_4_2 = 46,
- VID_STRONGSWAN_2_4_3 = 47,
- VID_STRONGSWAN_2_4_4 = 48,
- VID_STRONGSWAN_2_5_0 = 49,
- VID_STRONGSWAN_2_5_1 = 50,
- VID_STRONGSWAN_2_5_2 = 51,
- VID_STRONGSWAN_2_5_3 = 52,
- VID_STRONGSWAN_2_5_4 = 53,
- VID_STRONGSWAN_2_5_5 = 54,
- VID_STRONGSWAN_2_5_6 = 55,
- VID_STRONGSWAN_2_5_7 = 56,
- VID_STRONGSWAN_2_6_0 = 57,
- VID_STRONGSWAN_2_6_1 = 58,
- VID_STRONGSWAN_2_6_2 = 59,
- VID_STRONGSWAN_2_6_3 = 60,
- VID_STRONGSWAN_2_6_4 = 61,
- VID_STRONGSWAN_2_7_0 = 62,
- VID_STRONGSWAN_2_7_1 = 63,
- VID_STRONGSWAN_2_7_2 = 64,
- VID_STRONGSWAN_2_7_3 = 65,
- VID_STRONGSWAN_2_8_0 = 66,
- VID_STRONGSWAN_2_8_1 = 67,
- VID_STRONGSWAN_2_8_2 = 68,
- VID_STRONGSWAN_2_8_3 = 69,
- VID_STRONGSWAN_2_8_4 = 70,
- VID_STRONGSWAN_2_8_5 = 71,
- VID_STRONGSWAN_2_8_6 = 72,
- VID_STRONGSWAN_2_8_7 = 73,
- VID_STRONGSWAN_2_8_8 = 74,
- VID_STRONGSWAN_2_8_9 = 75,
- VID_STRONGSWAN_2_8_10 = 76,
- VID_STRONGSWAN_2_8_11 = 77,
+ VID_STRONGSWAN = 36,
+
+ VID_STRONGSWAN_2_8_0 = 37,
+ VID_STRONGSWAN_2_8_1 = 38,
+ VID_STRONGSWAN_2_8_2 = 39,
+ VID_STRONGSWAN_2_8_3 = 40,
+ VID_STRONGSWAN_2_8_4 = 41,
+ VID_STRONGSWAN_2_8_5 = 42,
+ VID_STRONGSWAN_2_8_6 = 43,
+ VID_STRONGSWAN_2_8_7 = 44,
+ VID_STRONGSWAN_2_8_8 = 45,
+ VID_STRONGSWAN_2_8_9 = 46,
+ VID_STRONGSWAN_2_8_10 = 47,
+ VID_STRONGSWAN_2_8_11 = 48,
- VID_STRONGSWAN_4_0_0 = 80,
- VID_STRONGSWAN_4_0_1 = 81,
- VID_STRONGSWAN_4_0_2 = 82,
- VID_STRONGSWAN_4_0_3 = 83,
- VID_STRONGSWAN_4_0_4 = 84,
- VID_STRONGSWAN_4_0_5 = 85,
- VID_STRONGSWAN_4_0_6 = 86,
- VID_STRONGSWAN_4_0_7 = 87,
VID_STRONGSWAN_4_1_0 = 88,
VID_STRONGSWAN_4_1_1 = 89,
VID_STRONGSWAN_4_1_2 = 90,
@@ -115,7 +80,6 @@ enum known_vendorid {
VID_STRONGSWAN_4_1_9 = 97,
VID_STRONGSWAN_4_1_10 = 98,
VID_STRONGSWAN_4_1_11 = 99,
-
VID_STRONGSWAN_4_2_0 =100,
VID_STRONGSWAN_4_2_1 =101,
VID_STRONGSWAN_4_2_2 =102,
diff --git a/src/pluto/whack_attribute.c b/src/pluto/whack_attribute.c
new file mode 100644
index 000000000..6a12f0c09
--- /dev/null
+++ b/src/pluto/whack_attribute.c
@@ -0,0 +1,365 @@
+/*
+ * 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.
+ */
+
+#include "whack_attribute.h"
+
+#include "log.h"
+
+/* these are defined as constants in constant.h but redefined as enum values in
+ * attributes/attributes.h */
+#undef INTERNAL_IP4_SERVER
+#undef INTERNAL_IP6_SERVER
+
+#include <hydra.h>
+#include <attributes/mem_pool.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_whack_attribute_t private_whack_attribute_t;
+
+/**
+ * private data of whack_attribute
+ */
+struct private_whack_attribute_t {
+
+ /**
+ * public functions
+ */
+ whack_attribute_t public;
+
+ /**
+ * list of pools, contains mem_pool_t
+ */
+ linked_list_t *pools;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * global object
+ */
+whack_attribute_t *whack_attr;
+
+/**
+ * compare pools by name
+ */
+static bool pool_match(mem_pool_t *current, char *name)
+{
+ return name && streq(name, current->get_name(current));
+}
+
+/**
+ * find a pool by name
+ */
+static mem_pool_t *find_pool(private_whack_attribute_t *this, char *name)
+{
+ mem_pool_t *found;
+ if (this->pools->find_first(this->pools, (linked_list_match_t)pool_match,
+ (void**)&found, name) == SUCCESS)
+ {
+ return found;
+ }
+ return NULL;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_whack_attribute_t *this, char *name, identification_t *id,
+ host_t *requested)
+{
+ mem_pool_t *pool;
+ host_t *addr = NULL;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ addr = pool->acquire_address(pool, id, requested);
+ }
+ this->lock->unlock(this->lock);
+ return addr;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+ private_whack_attribute_t *this, char *name, host_t *address,
+ identification_t *id)
+{
+ mem_pool_t *pool;
+ bool found = FALSE;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ found = pool->release_address(pool, address, id);
+ }
+ this->lock->unlock(this->lock);
+ return found;
+}
+
+METHOD(whack_attribute_t, add_pool, bool,
+ private_whack_attribute_t *this, const char *name,
+ const whack_end_t *right)
+{
+ mem_pool_t *pool;
+ host_t *base = NULL;
+ u_int32_t bits = 0;
+
+ /* named pool */
+ if (right->sourceip_mask <= 0)
+ {
+ return FALSE;
+ }
+
+ /* if %config, add an empty pool, otherwise */
+ if (right->sourceip)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("adding virtual IP address pool '%s': %s/%d",
+ name, right->sourceip, right->sourceip_mask);
+ );
+ base = host_create_from_string(right->sourceip, 0);
+ if (!base)
+ {
+ loglog(RC_LOG_SERIOUS, "virtual IP address invalid, discarded");
+ return FALSE;
+ }
+ bits = right->sourceip_mask;
+ }
+ pool = mem_pool_create((char*)name, base, bits);
+ DESTROY_IF(base);
+
+ this->lock->write_lock(this->lock);
+ this->pools->insert_last(this->pools, pool);
+ this->lock->unlock(this->lock);
+ return TRUE;
+}
+
+METHOD(whack_attribute_t, del_pool, void,
+ private_whack_attribute_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ mem_pool_t *pool;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (streq(name, pool->get_name(pool)))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("deleting virtual IP address pool '%s'", name)
+ );
+ this->pools->remove_at(this->pools, enumerator);
+ pool->destroy(pool);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Pool enumerator filter function, converts pool_t to name, size, ...
+ */
+static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
+ void *d1, u_int *size, void *d2, u_int *online,
+ void *d3, u_int *offline)
+{
+ mem_pool_t *pool = *poolp;
+ *name = pool->get_name(pool);
+ *size = pool->get_size(pool);
+ *online = pool->get_online(pool);
+ *offline = pool->get_offline(pool);
+ return TRUE;
+}
+
+METHOD(whack_attribute_t, create_pool_enumerator, enumerator_t*,
+ private_whack_attribute_t *this)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->pools->create_enumerator(this->pools),
+ (void*)pool_filter,
+ this->lock, (void*)this->lock->unlock);
+}
+
+METHOD(whack_attribute_t, create_lease_enumerator, enumerator_t*,
+ private_whack_attribute_t *this, char *name)
+{
+ mem_pool_t *pool;
+ this->lock->read_lock(this->lock);
+ pool = find_pool(this, name);
+ if (!pool)
+ {
+ this->lock->unlock(this->lock);
+ return NULL;
+ }
+ return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
+ (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * see header file
+ */
+void whack_attribute_finalize()
+{
+ private_whack_attribute_t *this;
+
+ if (whack_attr)
+ {
+ this = (private_whack_attribute_t*)whack_attr;
+ hydra->attributes->remove_provider(hydra->attributes,
+ &this->public.provider);
+ this->lock->destroy(this->lock);
+ this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+ free(this);
+ }
+}
+
+/**
+ * see header file
+ */
+void whack_attribute_initialize()
+{
+ private_whack_attribute_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .add_pool = _add_pool,
+ .del_pool = _del_pool,
+ .create_pool_enumerator = _create_pool_enumerator,
+ .create_lease_enumerator = _create_lease_enumerator,
+ },
+ .pools = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ hydra->attributes->add_provider(hydra->attributes, &this->public.provider);
+
+ whack_attr = &this->public;
+}
+
+/**
+ * list leases of a single pool
+ */
+static void pool_leases(char *pool, host_t *address,
+ identification_t *identification,
+ u_int size, u_int online, u_int offline)
+{
+
+ enumerator_t *enumerator;
+ identification_t *id;
+ host_t *lease;
+ bool on, found = FALSE;
+
+ whack_log(RC_COMMENT, "Leases in pool '%s', usage: %lu/%lu, %lu online",
+ pool, online + offline, size, online);
+ enumerator = whack_attr->create_lease_enumerator(whack_attr, pool);
+ while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
+ {
+ if ((!address && !identification) ||
+ (address && address->ip_equals(address, lease)) ||
+ (identification && identification->equals(identification, id)))
+ {
+ whack_log(RC_COMMENT, " %15H %s '%Y'",
+ lease, on ? "online" : "offline", id);
+ found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ whack_log(RC_COMMENT, " no matching leases found");
+ }
+}
+
+/**
+ * see header file
+ */
+void list_leases(char *name, char *addr, char *id)
+{
+ identification_t *identification = NULL;
+ host_t *address = NULL;
+ bool found = FALSE;
+ enumerator_t *enumerator;
+ u_int size, online, offline;
+ char *pool;
+
+ if (addr)
+ {
+ address = host_create_from_string(addr, 0);
+ }
+ if (id)
+ {
+ identification = identification_create_from_string(id);
+ }
+
+ enumerator = whack_attr->create_pool_enumerator(whack_attr);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (!name || streq(name, pool))
+ {
+ pool_leases(pool, address, identification, size, online, offline);
+ found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ if (name)
+ {
+ whack_log(RC_COMMENT, "pool '%s' not found", name);
+ }
+ else
+ {
+ whack_log(RC_COMMENT, "no pools found");
+ }
+ }
+ DESTROY_IF(identification);
+ DESTROY_IF(address);
+}
+
+/**
+ * see header file
+ */
+void show_pools(const char *name)
+{
+ enumerator_t *enumerator;
+ u_int size, online, offline;
+ char *pool;
+ bool first = TRUE;
+
+ enumerator = whack_attr->create_pool_enumerator(whack_attr);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (name && !streq(name, pool))
+ {
+ continue;
+ }
+ if (first)
+ {
+ first = FALSE;
+ whack_log(RC_COMMENT, "Virtual IP pools (size/online/offline):");
+ }
+ whack_log(RC_COMMENT, "\"%s\": %u/%u/%u", pool, size, online, offline);
+ }
+ enumerator->destroy(enumerator);
+}
diff --git a/src/pluto/whack_attribute.h b/src/pluto/whack_attribute.h
new file mode 100644
index 000000000..58441b973
--- /dev/null
+++ b/src/pluto/whack_attribute.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup whack_attribute
+ * @{ @ingroup pluto
+ */
+
+#ifndef WHACK_ATTRIBUTE_H_
+#define WHACK_ATTRIBUTE_H_
+
+#include <whack.h>
+#include <attributes/attribute_provider.h>
+
+typedef struct whack_attribute_t whack_attribute_t;
+
+/**
+ * Whack attribute provider (basically an in-memory IP address pool)
+ */
+struct whack_attribute_t {
+
+ /**
+ * Implements attribute provider interface
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Add a virtual IP address pool.
+ *
+ * @param name name of the pool
+ * @param right "right" end of whack message
+ * @return TRUE, if the pool was successfully added
+ */
+ bool (*add_pool)(whack_attribute_t *this, const char *name,
+ const whack_end_t *right);
+
+ /**
+ * Remove a virtual IP address pool.
+ *
+ * @param name name of the pool
+ */
+ void (*del_pool)(whack_attribute_t *this, char *name);
+
+ /**
+ * Create an enumerator over installed pools.
+ *
+ * Enumerator enumerates over
+ * char *pool, u_int size, u_int offline, u_int online.
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_pool_enumerator)(whack_attribute_t *this);
+
+ /**
+ * Create an enumerator over the leases of a pool.
+ *
+ * Enumerator enumerates over
+ * identification_t *id, host_t *address, bool online
+ *
+ * @param name name of the pool to enumerate
+ * @return enumerator, NULL if pool not found
+ */
+ enumerator_t* (*create_lease_enumerator)(whack_attribute_t *this,
+ char *name);
+};
+
+/**
+ * Global object to manage pools. Set between calls to
+ * whack_attribute_initialize() and whack_attribute_finalize().
+ */
+extern whack_attribute_t *whack_attr;
+
+/**
+ * Initialize the whack attribute provider
+ */
+void whack_attribute_initialize();
+
+/**
+ * Finalize the whack attribute provider
+ */
+void whack_attribute_finalize();
+
+/**
+ * List the leases matching the given parameters.
+ *
+ * @param name name of the pool, NULL for all pools
+ * @param addr ip address of the lease to list, NULL to ignore
+ * @param id id of the lease to list, NULL to ignore
+ */
+void list_leases(char *name, char *addr, char *id);
+
+/**
+ * List either all pools or the pool with a given name
+ *
+ * @param name name of the pool, NULL for all pools
+ */
+void show_pools(const char *name);
+
+#endif /** WHACK_ATTRIBUTE_H_ @}*/
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index d8e887955..0a29830ea 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -419,11 +419,11 @@ void list_x509cert_chain(const char *caption, cert_t* cert,
check_expiry(notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
key = certificate->get_public_key(certificate);
- if (key);
+ if (key)
{
whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
key_type_names, key->get_type(key),
- key->get_keysize(key) * BITS_PER_BYTE,
+ key->get_keysize(key) * BITS_PER_BYTE,
cert->smartcard ? ", on smartcard" :
(has_private_key(cert)? ", has private key" : ""));
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am
index 3693b7532..dd4a4a63d 100644
--- a/src/scepclient/Makefile.am
+++ b/src/scepclient/Makefile.am
@@ -1,16 +1,20 @@
ipsec_PROGRAMS = scepclient
scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c
+scepclient.o : $(top_builddir)/config.status
+
PLUTODIR=$(top_srcdir)/src/pluto
OPENACDIR=$(top_srcdir)/src/openac
WHACKDIR=$(top_srcdir)/src/whack
LIBFREESWANDIR=$(top_srcdir)/src/libfreeswan
LIBSTRONGSWANDIR=$(top_srcdir)/src/libstrongswan
+LIBHYDRADIR=$(top_srcdir)/src/libhydra
LIBCRYPTODIR=$(top_srcdir)/src/libcrypto
INCLUDES = \
-I$(LIBFREESWANDIR) \
-I$(LIBSTRONGSWANDIR) \
+-I$(LIBHYDRADIR) \
-I$(PLUTODIR) \
-I$(LIBCRYPTODIR) \
-I$(WHACKDIR)
diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in
index 8438b81f9..db930756a 100644
--- a/src/scepclient/Makefile.in
+++ b/src/scepclient/Makefile.in
@@ -228,6 +228,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -268,10 +269,12 @@ OPENACDIR = $(top_srcdir)/src/openac
WHACKDIR = $(top_srcdir)/src/whack
LIBFREESWANDIR = $(top_srcdir)/src/libfreeswan
LIBSTRONGSWANDIR = $(top_srcdir)/src/libstrongswan
+LIBHYDRADIR = $(top_srcdir)/src/libhydra
LIBCRYPTODIR = $(top_srcdir)/src/libcrypto
INCLUDES = \
-I$(LIBFREESWANDIR) \
-I$(LIBSTRONGSWANDIR) \
+-I$(LIBHYDRADIR) \
-I$(PLUTODIR) \
-I$(LIBCRYPTODIR) \
-I$(WHACKDIR)
@@ -659,6 +662,8 @@ uninstall-man: uninstall-man8
uninstall-man uninstall-man8
+scepclient.o : $(top_builddir)/config.status
+
constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
diff --git a/src/scepclient/loglite.c b/src/scepclient/loglite.c
index 539bb5f72..96dc54390 100644
--- a/src/scepclient/loglite.c
+++ b/src/scepclient/loglite.c
@@ -41,7 +41,7 @@ bool
/**
* @brief scepclient dbg function
*/
-static void scepclient_dbg(int level, char *fmt, ...)
+static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...)
{
int priority = LOG_INFO;
int debug_level;
diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c
index 576ce1dc5..385f6f328 100644
--- a/src/scepclient/scepclient.c
+++ b/src/scepclient/scepclient.c
@@ -289,7 +289,7 @@ static void print_plugins()
len += snprintf(&buf[len], BUF_LEN-len, "%s ", plugin);
}
enumerator->destroy(enumerator);
- DBG1(" loaded plugins: %s", buf);
+ DBG1(DBG_LIB, " loaded plugins: %s", buf);
}
/**
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index 7524b5f26..a235013f2 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -38,7 +38,7 @@ if USE_CHARON
AM_CFLAGS += -DSTART_CHARON
endif
-lex.yy.c: $(srcdir)/parser.l $(srcdir)/parser.y $(srcdir)/parser.h
+lex.yy.c: $(srcdir)/parser.l $(srcdir)/parser.y $(srcdir)/parser.h y.tab.h
$(LEX) $(srcdir)/parser.l
y.tab.c: $(srcdir)/parser.y $(srcdir)/parser.l $(srcdir)/parser.h
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index 79ea9de32..11449f465 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -232,6 +232,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
@@ -718,7 +719,7 @@ uninstall-man: uninstall-man5 uninstall-man8
uninstall-man8
-lex.yy.c: $(srcdir)/parser.l $(srcdir)/parser.y $(srcdir)/parser.h
+lex.yy.c: $(srcdir)/parser.l $(srcdir)/parser.y $(srcdir)/parser.h y.tab.h
$(LEX) $(srcdir)/parser.l
y.tab.c: $(srcdir)/parser.y $(srcdir)/parser.l $(srcdir)/parser.h
diff --git a/src/starter/args.c b/src/starter/args.c
index ebbd42cc8..512f2f46f 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -248,11 +248,12 @@ static const token_info_t token_info[] =
/* end keywords */
{ ARG_MISC, 0, NULL /* KW_HOST */ },
+ { ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
{ ARG_MISC, 0, NULL /* KW_NEXTHOP */ },
{ ARG_STR, offsetof(starter_end_t, subnet), NULL },
{ ARG_MISC, 0, NULL /* KW_SUBNETWITHIN */ },
{ ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
- { ARG_MISC, 0, NULL /* KW_SOURCEIP */ },
+ { ARG_STR, offsetof(starter_end_t, sourceip), NULL },
{ ARG_MISC, 0, NULL /* KW_NATIP */ },
{ ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
diff --git a/src/starter/cmp.c b/src/starter/cmp.c
index 8462a4819..33a057b44 100644
--- a/src/starter/cmp.c
+++ b/src/starter/cmp.c
@@ -43,6 +43,7 @@ starter_cmp_end(starter_end_t *c1, starter_end_t *c2)
{
ADDCMP(addr);
}
+ VARCMP(ikeport);
ADDCMP(nexthop);
VARCMP(has_client);
VARCMP(has_client_wildcard);
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 07cc11503..e9b9028d5 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -96,6 +96,8 @@ static void default_values(starter_config_t *cfg)
anyaddr(AF_INET, &cfg->conn_default.left.nexthop);
anyaddr(AF_INET, &cfg->conn_default.right.addr);
anyaddr(AF_INET, &cfg->conn_default.right.nexthop);
+ cfg->conn_default.left.ikeport = 500;
+ cfg->conn_default.right.ikeport = 500;
cfg->ca_default.seen = LEMPTY;
}
@@ -105,8 +107,7 @@ static void default_values(starter_config_t *cfg)
else if (streq(kw->value, sn)) { conn->policy &= ~fl; } \
else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
-static void
-load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
+static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
{
kw_list_t *kw;
@@ -193,11 +194,13 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
streq(value, "%config") || streq(value, "%cfg"))
{
/* request ip via config payload */
+ free(end->sourceip);
end->sourceip = NULL;
end->sourceip_mask = 1;
}
else
{ /* %poolname, strip %, serve ip requests */
+ free(end->sourceip);
end->sourceip = clone_str(value+1);
end->sourceip_mask = 0;
}
@@ -221,6 +224,7 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
goto err;
}
*pos = '\0';
+ free(end->sourceip);
end->sourceip = clone_str(value);
end->sourceip_mask = atoi(pos + 1);
}
@@ -232,7 +236,6 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
plog("# bad addr: %s=%s [%s]", name, value, ugh);
goto err;
}
- end->sourceip = clone_str(value);
end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ?
32 : 128;
}
@@ -419,8 +422,8 @@ err:
/*
* handles left|right=<FQDN> DNS resolution failure
*/
-static void
-handle_dns_failure( const char *label, starter_end_t *end, starter_config_t *cfg)
+static void handle_dns_failure(const char *label, starter_end_t *end,
+ starter_config_t *cfg)
{
if (end->dns_failed)
{
@@ -440,8 +443,8 @@ handle_dns_failure( const char *label, starter_end_t *end, starter_config_t *cfg
/*
* handles left|rightfirewall and left|rightupdown parameters
*/
-static void
-handle_firewall( const char *label, starter_end_t *end, starter_config_t *cfg)
+static void handle_firewall(const char *label, starter_end_t *end,
+ starter_config_t *cfg)
{
if (end->firewall && (end->seen & LELEM(KW_FIREWALL - KW_END_FIRST)))
{
@@ -461,8 +464,7 @@ handle_firewall( const char *label, starter_end_t *end, starter_config_t *cfg)
/*
* parse a conn section
*/
-static void
-load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
+static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
{
char *conn_name = (conn->name == NULL)? "%default":conn->name;
@@ -718,8 +720,7 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
/*
* initialize a conn object with the default conn
*/
-static void
-conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
+static void conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
{
memcpy(conn, def, sizeof(starter_conn_t));
conn->name = clone_str(name);
@@ -732,8 +733,7 @@ conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
/*
* parse a ca section
*/
-static void
-load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
+static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
{
char *ca_name = (ca->name == NULL)? "%default":ca->name;
@@ -786,8 +786,7 @@ load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
/*
* initialize a ca object with the default ca
*/
-static void
-ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
+static void ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
{
memcpy(ca, def, sizeof(starter_ca_t));
ca->name = clone_str(name);
@@ -795,11 +794,11 @@ ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
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 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)
+static void load_also_conns(starter_conn_t *conn, also_t *also,
+ starter_config_t *cfg)
{
while (also != NULL)
{
@@ -825,8 +824,8 @@ load_also_conns(starter_conn_t *conn, also_t *also, starter_config_t *cfg)
/*
* find a conn included by also
*/
-static kw_list_t*
-find_also_conn(const char* name, starter_conn_t *conn, starter_config_t *cfg)
+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;
@@ -852,11 +851,10 @@ find_also_conn(const char* name, starter_conn_t *conn, starter_config_t *cfg)
return NULL;
}
-static kw_list_t*
-find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg);
+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)
+static void load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
{
while (also != NULL)
{
@@ -882,8 +880,8 @@ load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
/*
* find a ca included by also
*/
-static kw_list_t*
-find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg)
+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;
@@ -912,8 +910,7 @@ find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg)
/*
* free the memory used by also_t objects
*/
-static void
-free_also(also_t *head)
+static void free_also(also_t *head)
{
while (head != NULL)
{
@@ -928,8 +925,7 @@ free_also(also_t *head)
/*
* free the memory used by a starter_conn_t object
*/
-static void
-confread_free_conn(starter_conn_t *conn)
+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);
@@ -950,8 +946,7 @@ confread_free_ca(starter_ca_t *ca)
/*
* free the memory used by a starter_config_t object
*/
-void
-confread_free(starter_config_t *cfg)
+void confread_free(starter_config_t *cfg)
{
starter_conn_t *conn = cfg->conn_first;
starter_ca_t *ca = cfg->ca_first;
@@ -986,8 +981,7 @@ confread_free(starter_config_t *cfg)
/*
* load and parse an IPsec configuration file
*/
-starter_config_t *
-confread_load(const char *file)
+starter_config_t* confread_load(const char *file)
{
starter_config_t *cfg = NULL;
config_parsed_t *cfgp;
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 7f3211628..199fab642 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -66,6 +66,7 @@ struct starter_end {
char *groups;
char *iface;
ip_address addr;
+ u_int ikeport;
ip_address nexthop;
char *subnet;
bool has_client;
diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5
index d4dd7238f..4cb1cb0fc 100644
--- a/src/starter/ipsec.conf.5
+++ b/src/starter/ipsec.conf.5
@@ -604,6 +604,13 @@ identity to use for a second authentication for the left participant
(IKEv2 only); defaults to
.BR leftid .
.TP
+.B leftikeport
+UDP port the left participant uses for IKE communication. Currently supported in
+IKEv2 connections only. If unspecified, port 500 is used with port floating to
+4500 if NAT is detected or MOBIKE enabled. Specifying a local IKE port
+different from the default additionally requires a socket implementation that
+listens to this port.
+.TP
.B leftnexthop
this parameter is not needed any more because the NETKEY IPsec stack does
not require explicit routing entries for the traffic to be tunneled.
diff --git a/src/starter/keywords.c b/src/starter/keywords.c
index e379f78e9..df39f0dc7 100644
--- a/src/starter/keywords.c
+++ b/src/starter/keywords.c
@@ -54,12 +54,12 @@ struct kw_entry {
kw_token_t token;
};
-#define TOTAL_KEYWORDS 119
+#define TOTAL_KEYWORDS 121
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
-#define MIN_HASH_VALUE 17
-#define MAX_HASH_VALUE 215
-/* maximum key range = 199, duplicates = 0 */
+#define MIN_HASH_VALUE 11
+#define MAX_HASH_VALUE 230
+/* maximum key range = 220, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -75,32 +75,32 @@ hash (str, len)
{
static const unsigned char asso_values[] =
{
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 12,
- 78, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 4, 216, 20, 216, 45,
- 55, 4, 77, 14, 78, 4, 216, 119, 4, 89,
- 46, 34, 29, 216, 6, 12, 5, 56, 34, 216,
- 4, 20, 5, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 26,
+ 75, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 2, 231, 25, 231, 40,
+ 61, 2, 114, 24, 3, 2, 231, 101, 2, 96,
+ 48, 35, 23, 231, 4, 10, 3, 69, 25, 231,
+ 2, 18, 16, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231
};
register int hval = len;
@@ -128,119 +128,121 @@ static const struct kw_entry wordlist[] =
{"right", KW_RIGHT},
{"lifetime", KW_KEYLIFE},
{"leftcert", KW_LEFTCERT,},
+ {"reauth", KW_REAUTH},
{"leftfirewall", KW_LEFTFIREWALL},
{"leftsendcert", KW_LEFTSENDCERT},
+ {"rightikeport", KW_RIGHTIKEPORT},
{"leftprotoport", KW_LEFTPROTOPORT},
{"type", KW_TYPE},
- {"rekey", KW_REKEY},
{"leftgroups", KW_LEFTGROUPS},
+ {"rekey", KW_REKEY},
{"rightsubnet", KW_RIGHTSUBNET},
{"rightsendcert", KW_RIGHTSENDCERT},
+ {"righthostaccess", KW_RIGHTHOSTACCESS},
+ {"xauth", KW_XAUTH},
{"leftallowany", KW_LEFTALLOWANY},
- {"rightgroups", KW_RIGHTGROUPS},
{"esp", KW_ESP},
+ {"leftnexthop", KW_LEFTNEXTHOP},
{"lifebytes", KW_LIFEBYTES},
{"rightrsasigkey", KW_RIGHTRSASIGKEY},
- {"lifepackets", KW_LIFEPACKETS},
- {"leftnexthop", KW_LEFTNEXTHOP},
+ {"rightauth", KW_RIGHTAUTH},
{"leftrsasigkey", KW_LEFTRSASIGKEY},
- {"leftca", KW_LEFTCA},
- {"eap", KW_EAP},
- {"strictcrlpolicy", KW_STRICTCRLPOLICY},
{"rightprotoport", KW_RIGHTPROTOPORT},
{"plutostart", KW_PLUTOSTART},
- {"also", KW_ALSO},
- {"rightallowany", KW_RIGHTALLOWANY},
+ {"strictcrlpolicy", KW_STRICTCRLPOLICY},
+ {"lifepackets", KW_LIFEPACKETS},
+ {"rightgroups", KW_RIGHTGROUPS},
{"rightsourceip", KW_RIGHTSOURCEIP},
+ {"eap", KW_EAP},
{"crluri", KW_CRLURI},
- {"leftnatip", KW_LEFTNATIP},
- {"lefthostaccess", KW_LEFTHOSTACCESS},
+ {"hidetos", KW_HIDETOS},
{"rightcert", KW_RIGHTCERT},
{"certuribase", KW_CERTURIBASE},
+ {"leftca", KW_LEFTCA},
+ {"leftnatip", KW_LEFTNATIP},
+ {"rightallowany", KW_RIGHTALLOWANY},
+ {"lefthostaccess", KW_LEFTHOSTACCESS},
+ {"crlcheckinterval", KW_CRLCHECKINTERVAL},
+ {"also", KW_ALSO},
{"packetdefault", KW_PACKETDEFAULT},
+ {"virtual_private", KW_VIRTUAL_PRIVATE},
{"plutostderrlog", KW_PLUTOSTDERRLOG},
- {"crluri1", KW_CRLURI},
- {"crlcheckinterval", KW_CRLCHECKINTERVAL},
+ {"leftsourceip", KW_LEFTSOURCEIP},
{"rightid", KW_RIGHTID},
- {"virtual_private", KW_VIRTUAL_PRIVATE},
- {"leftsubnet", KW_LEFTSUBNET},
{"cacert", KW_CACERT},
{"rightca", KW_RIGHTCA},
- {"leftsourceip", KW_LEFTSOURCEIP},
+ {"crluri1", KW_CRLURI},
{"inactivity", KW_INACTIVITY},
{"rightsubnetwithin", KW_RIGHTSUBNETWITHIN},
{"installpolicy", KW_INSTALLPOLICY},
- {"nat_traversal", KW_NAT_TRAVERSAL},
- {"ldapbase", KW_LDAPBASE},
+ {"leftauth", KW_LEFTAUTH},
{"leftupdown", KW_LEFTUPDOWN},
+ {"leftsubnet", KW_LEFTSUBNET},
{"rightnatip", KW_RIGHTNATIP},
{"ocspuri", KW_OCSPURI},
{"rightnexthop", KW_RIGHTNEXTHOP},
{"leftcert2", KW_LEFTCERT2,},
{"rightid2", KW_RIGHTID2},
- {"rekeyfuzz", KW_REKEYFUZZ},
+ {"nat_traversal", KW_NAT_TRAVERSAL},
{"compress", KW_COMPRESS},
- {"rightfirewall", KW_RIGHTFIREWALL},
- {"ocspuri1", KW_OCSPURI},
- {"ldaphost", KW_LDAPHOST},
- {"xauth", KW_XAUTH},
+ {"ldapbase", KW_LDAPBASE},
+ {"auth", KW_AUTH},
{"postpluto", KW_POSTPLUTO},
- {"eap_identity", KW_EAP_IDENTITY},
- {"plutodebug", KW_PLUTODEBUG},
+ {"charonstart", KW_CHARONSTART},
+ {"ike", KW_IKE},
+ {"ldaphost", KW_LDAPHOST},
{"leftca2", KW_LEFTCA2},
- {"auto", KW_AUTO},
- {"righthostaccess", KW_RIGHTHOSTACCESS},
{"dpddelay", KW_DPDDELAY},
- {"rightauth", KW_RIGHTAUTH},
+ {"ocspuri1", KW_OCSPURI},
{"rightauth2", KW_RIGHTAUTH2},
- {"pfs", KW_PFS},
- {"authby", KW_AUTHBY},
- {"rightupdown", KW_RIGHTUPDOWN},
+ {"eap_identity", KW_EAP_IDENTITY},
+ {"leftikeport", KW_LEFTIKEPORT},
+ {"plutodebug", KW_PLUTODEBUG},
+ {"cachecrls", KW_CACHECRLS},
+ {"charondebug", KW_CHARONDEBUG},
+ {"crluri2", KW_CRLURI2},
+ {"rightca2", KW_RIGHTCA2},
+ {"mediated_by", KW_MEDIATED_BY},
+ {"rightcert2", KW_RIGHTCERT2},
{"leftid", KW_LEFTID},
+ {"auto", KW_AUTO},
+ {"rightupdown", KW_RIGHTUPDOWN},
+ {"rightfirewall", KW_RIGHTFIREWALL},
+ {"authby", KW_AUTHBY},
{"leftsubnetwithin", KW_LEFTSUBNETWITHIN},
{"uniqueids", KW_UNIQUEIDS},
- {"dumpdir", KW_DUMPDIR},
- {"mediated_by", KW_MEDIATED_BY},
- {"ike", KW_IKE},
- {"cachecrls", KW_CACHECRLS},
{"prepluto", KW_PREPLUTO},
- {"force_keepalive", KW_FORCE_KEEPALIVE},
- {"hidetos", KW_HIDETOS},
+ {"keep_alive", KW_KEEP_ALIVE},
{"mobike", KW_MOBIKE},
- {"forceencaps", KW_FORCEENCAPS},
{"overridemtu", KW_OVERRIDEMTU},
- {"crluri2", KW_CRLURI2},
- {"rightca2", KW_RIGHTCA2},
- {"rightcert2", KW_RIGHTCERT2},
+ {"dumpdir", KW_DUMPDIR},
{"dpdaction", KW_DPDACTION},
- {"nocrsend", KW_NOCRSEND},
+ {"rekeyfuzz", KW_REKEYFUZZ},
{"leftid2", KW_LEFTID2},
- {"interfaces", KW_INTERFACES},
- {"leftauth", KW_LEFTAUTH},
+ {"keyingtries", KW_KEYINGTRIES},
+ {"pfs", KW_PFS},
+ {"nocrsend", KW_NOCRSEND},
+ {"keyexchange", KW_KEYEXCHANGE},
{"leftauth2", KW_LEFTAUTH2},
{"mediation", KW_MEDIATION},
{"rekeymargin", KW_REKEYMARGIN},
- {"keep_alive", KW_KEEP_ALIVE},
- {"auth", KW_AUTH},
- {"keyingtries", KW_KEYINGTRIES},
- {"me_peerid", KW_ME_PEERID},
- {"fragicmp", KW_FRAGICMP},
- {"margintime", KW_REKEYMARGIN},
{"ocspuri2", KW_OCSPURI2},
- {"reauth", KW_REAUTH},
{"pkcs11module", KW_PKCS11MODULE},
- {"pfsgroup", KW_PFSGROUP},
- {"marginbytes", KW_MARGINBYTES},
{"pkcs11keepstate", KW_PKCS11KEEPSTATE},
- {"marginpackets", KW_MARGINPACKETS},
- {"modeconfig", KW_MODECONFIG},
- {"keyexchange", KW_KEYEXCHANGE},
- {"charonstart", KW_CHARONSTART},
+ {"force_keepalive", KW_FORCE_KEEPALIVE},
+ {"me_peerid", KW_ME_PEERID},
+ {"forceencaps", KW_FORCEENCAPS},
{"pkcs11initargs", KW_PKCS11INITARGS},
- {"dpdtimeout", KW_DPDTIMEOUT},
{"pkcs11proxy", KW_PKCS11PROXY},
- {"charondebug", KW_CHARONDEBUG},
+ {"margintime", KW_REKEYMARGIN},
+ {"interfaces", KW_INTERFACES},
+ {"fragicmp", KW_FRAGICMP},
+ {"marginbytes", KW_MARGINBYTES},
+ {"marginpackets", KW_MARGINPACKETS},
+ {"dpdtimeout", KW_DPDTIMEOUT},
{"klipsdebug", KW_KLIPSDEBUG},
+ {"modeconfig", KW_MODECONFIG},
+ {"pfsgroup", KW_PFSGROUP},
{"keylife", KW_KEYLIFE},
{"ikelifetime", KW_IKELIFETIME}
};
@@ -248,27 +250,29 @@ static const struct kw_entry wordlist[] =
static const short lookup[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 0, -1, -1,
- 1, -1, -1, -1, 2, 3, -1, -1, 4, 5,
- -1, -1, 6, 7, -1, 8, 9, -1, 10, -1,
- 11, -1, -1, -1, 12, -1, -1, 13, 14, 15,
- 16, 17, 18, 19, 20, -1, 21, 22, 23, -1,
- 24, -1, 25, 26, 27, 28, 29, -1, 30, 31,
- 32, -1, 33, 34, 35, 36, 37, 38, -1, 39,
- -1, 40, 41, 42, 43, 44, -1, 45, -1, 46,
- -1, 47, -1, 48, -1, 49, 50, 51, -1, 52,
- 53, 54, -1, 55, 56, 57, 58, 59, -1, -1,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, -1,
- -1, 69, 70, 71, 72, -1, 73, 74, 75, 76,
- 77, 78, -1, 79, 80, 81, -1, 82, 83, 84,
- 85, 86, -1, 87, 88, -1, -1, 89, 90, 91,
- 92, 93, -1, 94, -1, -1, 95, 96, 97, -1,
- 98, 99, -1, -1, -1, 100, -1, -1, -1, 101,
- -1, 102, 103, -1, -1, -1, 104, 105, 106, 107,
- 108, 109, -1, 110, -1, 111, 112, -1, 113, -1,
- -1, 114, -1, -1, 115, -1, -1, -1, -1, -1,
- -1, -1, 116, -1, -1, -1, -1, -1, -1, -1,
- -1, 117, -1, -1, -1, 118
+ -1, 0, -1, -1, 1, -1, 2, 3, 4, -1,
+ 5, 6, -1, 7, 8, -1, -1, 9, 10, 11,
+ 12, -1, 13, -1, 14, 15, 16, -1, 17, -1,
+ 18, 19, 20, 21, -1, 22, 23, -1, 24, 25,
+ 26, 27, 28, 29, 30, -1, -1, 31, 32, 33,
+ 34, 35, 36, 37, 38, -1, 39, 40, -1, 41,
+ -1, -1, -1, 42, 43, -1, 44, 45, 46, 47,
+ 48, 49, -1, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, -1, -1, 60, -1, -1, 61, -1,
+ -1, 62, -1, -1, 63, 64, -1, -1, 65, 66,
+ -1, 67, 68, 69, -1, -1, 70, -1, 71, 72,
+ 73, -1, -1, -1, 74, -1, 75, -1, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, -1, 94, 95, -1,
+ 96, -1, -1, -1, 97, -1, 98, 99, 100, -1,
+ -1, 101, 102, -1, 103, -1, -1, 104, 105, -1,
+ 106, -1, 107, -1, 108, -1, -1, -1, -1, 109,
+ -1, 110, -1, -1, 111, -1, -1, -1, -1, 112,
+ 113, -1, 114, 115, -1, -1, -1, -1, 116, -1,
+ 117, -1, -1, 118, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 119, -1, -1, -1,
+ 120
};
#ifdef __GNUC__
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 8be31d148..6c3907a6a 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -118,6 +118,7 @@ typedef enum {
/* end keywords */
KW_HOST,
KW_NEXTHOP,
+ KW_IKEPORT,
KW_SUBNET,
KW_SUBNETWITHIN,
KW_PROTOPORT,
@@ -145,6 +146,7 @@ typedef enum {
/* left end keywords */
KW_LEFT,
+ KW_LEFTIKEPORT,
KW_LEFTNEXTHOP,
KW_LEFTSUBNET,
KW_LEFTSUBNETWITHIN,
@@ -172,6 +174,7 @@ typedef enum {
/* right end keywords */
KW_RIGHT,
+ KW_RIGHTIKEPORT,
KW_RIGHTNEXTHOP,
KW_RIGHTSUBNET,
KW_RIGHTSUBNETWITHIN,
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index adf3069bf..12037a685 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -98,6 +98,7 @@ ocspuri1, KW_OCSPURI
ocspuri2, KW_OCSPURI2
certuribase, KW_CERTURIBASE
left, KW_LEFT
+leftikeport, KW_LEFTIKEPORT
leftnexthop, KW_LEFTNEXTHOP
leftsubnet, KW_LEFTSUBNET
leftsubnetwithin, KW_LEFTSUBNETWITHIN
@@ -120,6 +121,7 @@ leftca, KW_LEFTCA
leftca2, KW_LEFTCA2
leftgroups, KW_LEFTGROUPS
right, KW_RIGHT
+rightikeport, KW_RIGHTIKEPORT
rightnexthop, KW_RIGHTNEXTHOP
rightsubnet, KW_RIGHTSUBNET
rightsubnetwithin, KW_RIGHTSUBNETWITHIN
diff --git a/src/starter/lex.yy.c b/src/starter/lex.yy.c
index 4596c0cc3..13bf87f0b 100644
--- a/src/starter/lex.yy.c
+++ b/src/starter/lex.yy.c
@@ -513,7 +513,8 @@ char *yytext;
#define MAX_INCLUDE_DEPTH 20
extern void yyerror(const char *);
-extern int yylex (void);
+extern int yylex(void);
+extern int yylex_destroy(void);
static struct {
int stack_ptr;
@@ -557,6 +558,7 @@ void _parser_y_fini (void)
fclose(__parser_y_private.file[i]);
}
memset(&__parser_y_private, 0, sizeof(__parser_y_private));
+ yylex_destroy();
}
int _parser_y_include (const char *filename)
@@ -617,7 +619,7 @@ int _parser_y_include (const char *filename)
return 0;
}
-#line 621 "lex.yy.c"
+#line 623 "lex.yy.c"
#define INITIAL 0
@@ -805,10 +807,10 @@ YY_DECL
register char *yy_cp, *yy_bp;
register int yy_act;
-#line 133 "./parser.l"
+#line 135 "./parser.l"
-#line 812 "lex.yy.c"
+#line 814 "lex.yy.c"
if ( !(yy_init) )
{
@@ -893,7 +895,7 @@ do_action: /* This label is used only to access EOF actions. */
goto yy_find_action;
case YY_STATE_EOF(INITIAL):
-#line 135 "./parser.l"
+#line 137 "./parser.l"
{
if (__parser_y_private.filename[__parser_y_private.stack_ptr]) {
free(__parser_y_private.filename[__parser_y_private.stack_ptr]);
@@ -913,23 +915,23 @@ case YY_STATE_EOF(INITIAL):
YY_BREAK
case 1:
YY_RULE_SETUP
-#line 152 "./parser.l"
+#line 154 "./parser.l"
return FIRST_SPACES;
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 154 "./parser.l"
+#line 156 "./parser.l"
/* ignore spaces in line */ ;
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 156 "./parser.l"
+#line 158 "./parser.l"
return EQUAL;
YY_BREAK
case 4:
/* rule 4 can match eol */
YY_RULE_SETUP
-#line 158 "./parser.l"
+#line 160 "./parser.l"
{
__parser_y_private.line[__parser_y_private.stack_ptr]++;
return EOL;
@@ -937,37 +939,37 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 163 "./parser.l"
+#line 165 "./parser.l"
return CONFIG;
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 164 "./parser.l"
+#line 166 "./parser.l"
return SETUP;
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 165 "./parser.l"
+#line 167 "./parser.l"
return CONN;
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 166 "./parser.l"
+#line 168 "./parser.l"
return CA;
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 167 "./parser.l"
+#line 169 "./parser.l"
return INCLUDE;
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 168 "./parser.l"
+#line 170 "./parser.l"
return FILE_VERSION;
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 170 "./parser.l"
+#line 172 "./parser.l"
{
yylval.s = strdup(yytext);
return STRING;
@@ -975,7 +977,7 @@ YY_RULE_SETUP
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 175 "./parser.l"
+#line 177 "./parser.l"
{
yylval.s = strdup(yytext+1);
if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0';
@@ -984,15 +986,15 @@ YY_RULE_SETUP
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 181 "./parser.l"
+#line 183 "./parser.l"
yyerror(yytext);
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 183 "./parser.l"
+#line 185 "./parser.l"
ECHO;
YY_BREAK
-#line 996 "lex.yy.c"
+#line 998 "lex.yy.c"
case YY_END_OF_BUFFER:
{
@@ -1954,7 +1956,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
-#line 183 "./parser.l"
+#line 185 "./parser.l"
diff --git a/src/starter/parser.l b/src/starter/parser.l
index 5857c0815..c45847c5c 100644
--- a/src/starter/parser.l
+++ b/src/starter/parser.l
@@ -24,7 +24,8 @@
#define MAX_INCLUDE_DEPTH 20
extern void yyerror(const char *);
-extern int yylex (void);
+extern int yylex(void);
+extern int yylex_destroy(void);
static struct {
int stack_ptr;
@@ -68,6 +69,7 @@ void _parser_y_fini (void)
fclose(__parser_y_private.file[i]);
}
memset(&__parser_y_private, 0, sizeof(__parser_y_private));
+ yylex_destroy();
}
int _parser_y_include (const char *filename)
diff --git a/src/starter/parser.y b/src/starter/parser.y
index 4533228c2..b0b1f6f21 100644
--- a/src/starter/parser.y
+++ b/src/starter/parser.y
@@ -156,21 +156,20 @@ statement_kw:
%%
-void
-yyerror(const char *s)
+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 *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_init(const char *f);
+ extern void _parser_y_fini(void);
extern FILE *yyin;
memset(parser_errstring, 0, ERRSTRING_LEN+1);
@@ -231,11 +230,11 @@ parser_load_conf(const char *file)
cfg = NULL;
}
+ _parser_y_fini();
return cfg;
}
-static void
-parser_free_kwlist(kw_list_t *list)
+static void parser_free_kwlist(kw_list_t *list)
{
kw_list_t *elt;
@@ -248,8 +247,7 @@ parser_free_kwlist(kw_list_t *list)
}
}
-void
-parser_free_conf(config_parsed_t *cfg)
+void parser_free_conf(config_parsed_t *cfg)
{
section_list_t *sec;
if (cfg)
diff --git a/src/starter/starter.c b/src/starter/starter.c
index 0aab76d43..50ef9c07b 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -28,6 +28,7 @@
#include <grp.h>
#include <freeswan.h>
+#include <library.h>
#include "../pluto/constants.h"
#include "../pluto/defs.h"
@@ -245,6 +246,9 @@ int main (int argc, char **argv)
log_to_stderr = TRUE;
base_debugging = DBG_NONE;
+ library_init(NULL);
+ atexit(library_deinit);
+
/* parse command line */
for (i = 1; i < argc; i++)
{
@@ -358,6 +362,7 @@ int main (int argc, char **argv)
if (stat(STARTER_PID_FILE, &stb) == 0)
{
plog("starter is already running (%s exists) -- no fork done", STARTER_PID_FILE);
+ confread_free(cfg);
exit(LSB_RC_SUCCESS);
}
@@ -388,6 +393,7 @@ int main (int argc, char **argv)
plog("can't fork: %s", strerror(errno));
break;
default:
+ confread_free(cfg);
exit(LSB_RC_SUCCESS);
}
}
@@ -422,11 +428,8 @@ int main (int argc, char **argv)
confread_free(cfg);
unlink(STARTER_PID_FILE);
unlink(INFO_FILE);
-#ifdef LEAK_DETECTIVE
- report_leaks();
-#endif /* LEAK_DETECTIVE */
- close_log();
plog("ipsec starter stopped");
+ close_log();
exit(LSB_RC_SUCCESS);
}
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 665350c00..d877661ec 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -186,6 +186,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
msg_end->updown = push_string(msg, conn_end->updown);
ip_address2string(&conn_end->addr, buffer, sizeof(buffer));
msg_end->address = push_string(msg, buffer);
+ msg_end->ikeport = conn_end->ikeport;
msg_end->subnets = push_string(msg, conn_end->subnet);
msg_end->sourceip = push_string(msg, conn_end->sourceip);
msg_end->sourceip_mask = conn_end->sourceip_mask;
diff --git a/src/starter/starterwhack.c b/src/starter/starterwhack.c
index 67916395f..527142a4e 100644
--- a/src/starter/starterwhack.c
+++ b/src/starter/starterwhack.c
@@ -91,6 +91,8 @@ static int send_whack_msg (whack_message_t *msg)
|| !pack_str(&msg->ike, &str_next, &str_roof)
|| !pack_str(&msg->esp, &str_next, &str_roof)
|| !pack_str(&msg->sc_data, &str_next, &str_roof)
+ || !pack_str(&msg->whack_lease_ip, &str_next, &str_roof)
+ || !pack_str(&msg->whack_lease_id, &str_next, &str_roof)
|| (str_roof - str_next < msg->keyval.len))
{
plog("send_wack_msg(): can't pack strings");
@@ -138,14 +140,12 @@ static void init_whack_msg(whack_message_t *msg)
msg->magic = WHACK_MAGIC;
}
-static char *connection_name(starter_conn_t *conn)
+static char *connection_name(starter_conn_t *conn, char *buf, size_t size)
{
/* if connection name is '%auto', create a new name like conn_xxxxx */
- static char buf[32];
-
if (streq(conn->name, "%auto"))
{
- sprintf(buf, "conn_%ld", conn->id);
+ snprintf(buf, size, "conn_%ld", conn->id);
return buf;
}
return conn->name;
@@ -161,7 +161,7 @@ static void set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family
w->has_client = end->has_client;
w->sourceip = end->sourceip;
w->sourceip_mask = end->sourceip_mask;
-
+
if (end->sourceip && end->sourceip_mask > 0)
{
ttoaddr(end->sourceip, 0, ip_version(end->sourceip), &w->host_srcip);
@@ -226,10 +226,11 @@ starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
{
const char *err;
static char keyspace[1024 + 4];
- char buf[ADDRTOT_BUF];
+ char buf[ADDRTOT_BUF], name[32];
whack_message_t msg;
init_whack_msg(&msg);
+ connection_name(conn, name, sizeof(name));
msg.whack_key = TRUE;
msg.pubkey_alg = PUBKEY_ALG_RSA;
@@ -246,7 +247,7 @@ starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
err = atobytes(end->rsakey, 0, keyspace, sizeof(keyspace), &msg.keyval.len);
if (err)
{
- plog("conn %s/%s: rsakey malformed [%s]", connection_name(conn), lr, err);
+ plog("conn %s/%s: rsakey malformed [%s]", name, lr, err);
return 1;
}
if (end->id)
@@ -266,13 +267,14 @@ starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
int starter_whack_add_conn(starter_conn_t *conn)
{
+ char esp_buf[256], name[32];
whack_message_t msg;
int r;
init_whack_msg(&msg);
msg.whack_connection = TRUE;
- msg.name = connection_name(conn);
+ msg.name = connection_name(conn, name, sizeof(name));
msg.ikev1 = conn->keyexchange != KEY_EXCHANGE_IKEV2;
msg.addr_family = conn->addr_family;
@@ -302,8 +304,6 @@ int starter_whack_add_conn(starter_conn_t *conn)
/* taken from pluto/whack.c */
if (msg.pfsgroup)
{
- char esp_buf[256];
-
snprintf(esp_buf, sizeof (esp_buf), "%s;%s"
, msg.esp ? msg.esp : ""
, msg.pfsgroup ? msg.pfsgroup : "");
@@ -331,32 +331,35 @@ int starter_whack_add_conn(starter_conn_t *conn)
int starter_whack_del_conn(starter_conn_t *conn)
{
+ char name[32];
whack_message_t msg;
init_whack_msg(&msg);
msg.whack_delete = TRUE;
- msg.name = connection_name(conn);
+ msg.name = connection_name(conn, name, sizeof(name));
return send_whack_msg(&msg);
}
int starter_whack_route_conn(starter_conn_t *conn)
{
+ char name[32];
whack_message_t msg;
init_whack_msg(&msg);
msg.whack_route = TRUE;
- msg.name = connection_name(conn);
+ msg.name = connection_name(conn, name, sizeof(name));
return send_whack_msg(&msg);
}
int starter_whack_initiate_conn(starter_conn_t *conn)
{
+ char name[32];
whack_message_t msg;
init_whack_msg(&msg);
msg.whack_initiate = TRUE;
msg.whack_async = TRUE;
- msg.name = connection_name(conn);
+ msg.name = connection_name(conn, name, sizeof(name));
return send_whack_msg(&msg);
}
diff --git a/src/starter/y.tab.c b/src/starter/y.tab.c
index b78c1b1f9..504b5589e 100644
--- a/src/starter/y.tab.c
+++ b/src/starter/y.tab.c
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ 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, or (at your option)
- any later version.
-
+ 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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ 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
@@ -29,7 +28,7 @@
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. */
@@ -47,7 +46,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -55,45 +54,20 @@
/* Pure parsers. */
#define YYPURE 0
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
+/* Push parsers. */
+#define YYPUSH 0
+/* Pull parsers. */
+#define YYPULL 1
-/* 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
-
+/* Using locations. */
+#define YYLSP_NEEDED 0
/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
#line 1 "./parser.y"
/* strongSwan config file parser (parser.y)
@@ -148,6 +122,9 @@ extern kw_entry_t *in_word_set (char *str, unsigned int len);
+/* Line 189 of yacc.c */
+#line 127 "y.tab.c"
+
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
@@ -166,25 +143,63 @@ extern kw_entry_t *in_word_set (char *str, unsigned int len);
# define YYTOKEN_TABLE 0
#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 214 of yacc.c */
#line 54 "./parser.y"
-{ char *s; }
-/* Line 187 of yacc.c. */
-#line 175 "y.tab.c"
- YYSTYPE;
+ char *s;
+
+
+/* Line 214 of yacc.c */
+#line 191 "y.tab.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
-
/* Copy the second part of user declarations. */
-/* Line 216 of yacc.c. */
-#line 188 "y.tab.c"
+/* Line 264 of yacc.c */
+#line 203 "y.tab.c"
#ifdef short
# undef short
@@ -259,14 +274,14 @@ typedef short int yytype_int16;
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
-YYID (int i)
+YYID (int yyi)
#else
static int
-YYID (i)
- int i;
+YYID (yyi)
+ int yyi;
#endif
{
- return i;
+ return yyi;
}
#endif
@@ -347,9 +362,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- };
+ 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)
@@ -383,12 +398,12 @@ union yyalloc
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) \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
@@ -484,7 +499,7 @@ 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",
+ "config_file", "section_or_include", "$@1", "$@2", "$@3", "$@4",
"kw_section", "statement_kw", 0
};
#endif
@@ -758,17 +773,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
#else
static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
#endif
{
YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
YYFPRINTF (stderr, "\n");
}
@@ -802,11 +820,11 @@ yy_reduce_print (yyvsp, yyrule)
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
- fprintf (stderr, " $%d = ", yyi + 1);
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
);
- fprintf (stderr, "\n");
+ YYFPRINTF (stderr, "\n");
}
}
@@ -1086,10 +1104,8 @@ yydestruct (yymsg, yytype, yyvaluep)
break;
}
}
-
/* Prevent warnings from -Wmissing-prototypes. */
-
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
@@ -1105,11 +1121,10 @@ int yyparse ();
#endif /* ! YYPARSE_PARAM */
-
-/* The look-ahead symbol. */
+/* The lookahead symbol. */
int yychar;
-/* The semantic value of the look-ahead symbol. */
+/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
/* Number of syntax errors so far. */
@@ -1117,9 +1132,9 @@ int yynerrs;
-/*----------.
-| yyparse. |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1143,66 +1158,68 @@ yyparse ()
#endif
#endif
{
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
+ Refer to the stacks thru 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;
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
-
- YYSIZE_T yystacksize = YYINITDEPTH;
+ YYSIZE_T yystacksize;
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
/* 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;
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ yychar = YYEMPTY; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
-
yyssp = yyss;
yyvsp = yyvs;
@@ -1232,7 +1249,6 @@ yyparse ()
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
@@ -1240,7 +1256,6 @@ yyparse ()
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
-
&yystacksize);
yyss = yyss1;
@@ -1263,9 +1278,8 @@ yyparse ()
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
@@ -1276,7 +1290,6 @@ yyparse ()
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
-
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
@@ -1286,6 +1299,9 @@ yyparse ()
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
goto yybackup;
/*-----------.
@@ -1294,16 +1310,16 @@ yyparse ()
yybackup:
/* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
+ lookahead token if we need one and don't already have one. */
- /* First try to decide what to do without reference to look-ahead token. */
+ /* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
- /* Not known => get a look-ahead token if don't already have one. */
+ /* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
@@ -1335,20 +1351,16 @@ yybackup:
goto yyreduce;
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
- /* Shift the look-ahead token. */
+ /* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
yystate = yyn;
*++yyvsp = yylval;
@@ -1388,6 +1400,8 @@ yyreduce:
switch (yyn)
{
case 4:
+
+/* Line 1455 of yacc.c */
#line 71 "./parser.y"
{
free((yyvsp[(2) - (3)].s));
@@ -1395,6 +1409,8 @@ yyreduce:
break;
case 5:
+
+/* Line 1455 of yacc.c */
#line 75 "./parser.y"
{
_parser_kw = &(_parser_cfg->config_setup);
@@ -1403,6 +1419,8 @@ yyreduce:
break;
case 7:
+
+/* Line 1455 of yacc.c */
#line 80 "./parser.y"
{
section_list_t *section = malloc_thing(section_list_t);
@@ -1422,6 +1440,8 @@ yyreduce:
break;
case 9:
+
+/* Line 1455 of yacc.c */
#line 96 "./parser.y"
{
section_list_t *section = malloc_thing(section_list_t);
@@ -1440,6 +1460,8 @@ yyreduce:
break;
case 11:
+
+/* Line 1455 of yacc.c */
#line 111 "./parser.y"
{
extern void _parser_y_include (const char *f);
@@ -1449,6 +1471,8 @@ yyreduce:
break;
case 16:
+
+/* Line 1455 of yacc.c */
#line 126 "./parser.y"
{
kw_list_t *new;
@@ -1477,6 +1501,8 @@ yyreduce:
break;
case 17:
+
+/* Line 1455 of yacc.c */
#line 151 "./parser.y"
{
free((yyvsp[(1) - (2)].s));
@@ -1484,8 +1510,9 @@ yyreduce:
break;
-/* Line 1267 of yacc.c. */
-#line 1489 "y.tab.c"
+
+/* Line 1455 of yacc.c */
+#line 1516 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1496,7 +1523,6 @@ yyreduce:
*++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. */
@@ -1561,7 +1587,7 @@ yyerrlab:
if (yyerrstatus == 3)
{
- /* If just tried and failed to reuse look-ahead token after an
+ /* If just tried and failed to reuse lookahead token after an
error, discard it. */
if (yychar <= YYEOF)
@@ -1578,7 +1604,7 @@ yyerrlab:
}
}
- /* Else will try to reuse look-ahead token after shifting the error
+ /* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -1635,9 +1661,6 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
*++yyvsp = yylval;
@@ -1662,7 +1685,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -1673,7 +1696,7 @@ yyexhaustedlab:
#endif
yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
+ if (yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
@@ -1699,24 +1722,25 @@ yyreturn:
}
+
+/* Line 1675 of yacc.c */
#line 157 "./parser.y"
-void
-yyerror(const char *s)
+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 *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_init(const char *f);
+ extern void _parser_y_fini(void);
extern FILE *yyin;
memset(parser_errstring, 0, ERRSTRING_LEN+1);
@@ -1777,11 +1801,11 @@ parser_load_conf(const char *file)
cfg = NULL;
}
+ _parser_y_fini();
return cfg;
}
-static void
-parser_free_kwlist(kw_list_t *list)
+static void parser_free_kwlist(kw_list_t *list)
{
kw_list_t *elt;
@@ -1794,8 +1818,7 @@ parser_free_kwlist(kw_list_t *list)
}
}
-void
-parser_free_conf(config_parsed_t *cfg)
+void parser_free_conf(config_parsed_t *cfg)
{
section_list_t *sec;
if (cfg)
diff --git a/src/starter/y.tab.h b/src/starter/y.tab.h
index 871de1e97..caf6ea172 100644
--- a/src/starter/y.tab.h
+++ b/src/starter/y.tab.h
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ 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, or (at your option)
- any later version.
-
+ 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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ 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
@@ -29,10 +28,11 @@
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. */
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -68,15 +68,21 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
#line 54 "./parser.y"
-{ char *s; }
-/* Line 1489 of yacc.c. */
-#line 75 "y.tab.h"
- YYSTYPE;
+ char *s;
+
+
+/* Line 1676 of yacc.c */
+#line 80 "y.tab.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;
+
diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in
index 82f2be13d..4353928b5 100644
--- a/src/stroke/Makefile.in
+++ b/src/stroke/Makefile.in
@@ -197,6 +197,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 955e49535..4fa0f76a8 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -27,6 +27,8 @@
#include <stddef.h>
#include <string.h>
+#include <library.h>
+
#include "stroke_msg.h"
#include "stroke_keywords.h"
@@ -96,7 +98,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
{
if (fgets(buffer, sizeof(buffer), stdin))
{
- if (write(sock, buffer, strlen(buffer)));
+ ignore_result(write(sock, buffer, strlen(buffer)));
}
}
}
@@ -129,11 +131,13 @@ static int add_connection(char *name,
msg.add_conn.me.id = push_string(&msg, my_id);
msg.add_conn.me.address = push_string(&msg, my_addr);
+ msg.add_conn.me.ikeport = 500;
msg.add_conn.me.subnets = push_string(&msg, my_nets);
msg.add_conn.me.sendcert = 1;
msg.add_conn.other.id = push_string(&msg, other_id);
msg.add_conn.other.address = push_string(&msg, other_addr);
+ msg.add_conn.other.ikeport = 500;
msg.add_conn.other.subnets = push_string(&msg, other_nets);
msg.add_conn.other.sendcert = 1;
@@ -355,6 +359,9 @@ int main(int argc, char *argv[])
const stroke_token_t *token;
int res = 0;
+ library_init(NULL);
+ atexit(library_deinit);
+
if (argc < 2)
{
exit_usage(NULL);
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 56a7a158f..ffc67039e 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -137,6 +137,7 @@ struct stroke_end_t {
char *groups;
char *updown;
char *address;
+ u_int16_t ikeport;
char *sourceip;
int sourceip_mask;
char *subnets;
diff --git a/src/whack/Makefile.in b/src/whack/Makefile.in
index eb6238d80..098e5110e 100644
--- a/src/whack/Makefile.in
+++ b/src/whack/Makefile.in
@@ -196,6 +196,7 @@ ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
libstrongswan_plugins = @libstrongswan_plugins@
linux_headers = @linux_headers@
localedir = @localedir@
diff --git a/src/whack/whack.c b/src/whack/whack.c
index c458d6760..5f986108b 100644
--- a/src/whack/whack.c
+++ b/src/whack/whack.c
@@ -185,6 +185,10 @@ static void help(void)
" [--debug-private]"
"\n\n"
#endif
+ "leases: whack --leases"
+ " [--name <connection_name>]"
+ " [--lease-addr <ip-address> | --lease-id <identity>]"
+ "\n\n"
"listen: whack"
" (--listen | --unlisten)"
"\n\n"
@@ -322,6 +326,10 @@ enum {
OPT_LISTEN,
OPT_UNLISTEN,
+ OPT_LEASES,
+ OPT_LEASEADDR,
+ OPT_LEASEID,
+
OPT_PURGEOCSP,
OPT_REREADSECRETS,
@@ -519,6 +527,10 @@ static const struct option long_opts[] = {
{ "listen", no_argument, NULL, OPT_LISTEN + OO },
{ "unlisten", no_argument, NULL, OPT_UNLISTEN + OO },
+ { "leases", no_argument, NULL, OPT_LEASES + OO },
+ { "lease-addr", required_argument, NULL, OPT_LEASEADDR + OO },
+ { "lease-id", required_argument, NULL, OPT_LEASEID + OO },
+
{ "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO },
{ "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO },
@@ -1103,6 +1115,18 @@ int main(int argc, char **argv)
diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
continue;
+ case OPT_LEASES: /* --leases */
+ msg.whack_leases = TRUE;
+ continue;
+
+ case OPT_LEASEADDR: /* --lease-addr <ip-address> */
+ msg.whack_lease_ip = optarg; /* decoded by Pluto */
+ continue;
+
+ case OPT_LEASEID: /* --lease-id <identity> */
+ msg.whack_lease_id = optarg; /* decoded by Pluto */
+ continue;
+
case OPT_LISTEN: /* --listen */
msg.whack_listen = TRUE;
continue;
@@ -1618,6 +1642,12 @@ int main(int argc, char **argv)
break;
}
+ /* check leases */
+ if (LHAS(opts_seen, OPT_LEASEADDR) && LHAS(opts_seen, OPT_LEASEID))
+ {
+ diag("--lease-addr and --lease-id cannot be used together");
+ }
+
/* check connection description */
if (LHAS(opts_seen, OPT_CD))
{
@@ -1682,7 +1712,7 @@ int main(int argc, char **argv)
if (!LHAS(opts_seen, OPT_NAME) && !msg.whack_ca)
diag("missing --name <connection_name>");
}
- else if (!msg.whack_options && !msg.whack_status)
+ else if (!msg.whack_options && !msg.whack_status && !msg.whack_leases)
{
if (LHAS(opts_seen, OPT_NAME))
diag("no reason for --name");
@@ -1698,9 +1728,10 @@ int main(int argc, char **argv)
|| msg.whack_delete || msg.whack_deletestate
|| msg.whack_initiate || msg.whack_oppo_initiate || msg.whack_terminate
|| msg.whack_route || msg.whack_unroute || msg.whack_listen
- || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp || msg.whack_reread
- || msg.whack_ca || msg.whack_status || msg.whack_options || msg.whack_shutdown
- || msg.whack_sc_op))
+ || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp
+ || msg.whack_reread || msg.whack_ca || msg.whack_status
+ || msg.whack_options || msg.whack_shutdown || msg.whack_sc_op
+ || msg.whack_leases))
{
diag("no action specified; try --help for hints");
}
@@ -1771,6 +1802,8 @@ int main(int argc, char **argv)
|| !pack_str(&msg.ike) /* string 24 */
|| !pack_str(&msg.esp) /* string 25 */
|| !pack_str(&msg.sc_data) /* string 26 */
+ || !pack_str(&msg.whack_lease_ip) /* string 27 */
+ || !pack_str(&msg.whack_lease_id) /* string 28 */
|| str_roof - next_str < (ptrdiff_t)msg.keyval.len)
diag("too many bytes of strings to fit in message to pluto");
diff --git a/src/whack/whack.h b/src/whack/whack.h
index 3f66a7b4f..b495d3489 100644
--- a/src/whack/whack.h
+++ b/src/whack/whack.h
@@ -65,7 +65,7 @@ struct whack_end {
int sourceip_mask;
ip_address host_addr;
ip_address host_nexthop;
- ip_address host_srcip;
+ ip_address host_srcip;
ip_subnet client;
bool key_from_DNS_on_demand;
bool has_client;
@@ -177,6 +177,10 @@ struct whack_message {
bool whack_deletestate;
so_serial_t whack_deletestateno;
+ /* for WHACK_LEASES: */
+ bool whack_leases;
+ char *whack_lease_ip, *whack_lease_id;
+
/* for WHACK_LISTEN: */
bool whack_listen, whack_unlisten;