From 518dd33c94e041db0444c7d1f33da363bb8e3faf Mon Sep 17 00:00:00 2001 From: Yves-Alexis Perez Date: Thu, 24 Mar 2016 11:59:32 +0100 Subject: Imported Upstream version 5.4.0 --- src/Makefile.am | 4 - src/Makefile.in | 82 +- src/_copyright/Makefile.in | 2 + src/_updown/Makefile.in | 2 + src/aikgen/Makefile.in | 2 + src/charon-cmd/Makefile.am | 2 - src/charon-cmd/Makefile.in | 5 +- src/charon-cmd/charon-cmd.c | 6 - src/charon-nm/Makefile.am | 2 - src/charon-nm/Makefile.in | 5 +- src/charon-nm/charon-nm.c | 11 - src/charon-svc/Makefile.am | 2 - src/charon-svc/Makefile.in | 5 +- src/charon-svc/charon-svc.c | 32 +- src/charon-systemd/Makefile.am | 6 +- src/charon-systemd/Makefile.in | 12 +- src/charon-systemd/charon-systemd.c | 16 +- src/charon-tkm/Makefile.am | 6 +- src/charon-tkm/Makefile.in | 8 +- src/charon-tkm/src/charon-tkm.c | 10 - src/charon-tkm/src/ees/ees_callbacks.c | 8 +- src/charon-tkm/tests/keymat_tests.c | 1 - src/charon-tkm/tests/tests.c | 5 - src/charon/Android.mk | 3 +- src/charon/Makefile.am | 2 - src/charon/Makefile.in | 5 +- src/charon/charon.c | 11 - src/checksum/Makefile.am | 10 - src/checksum/Makefile.in | 79 +- src/checksum/checksum_builder.c | 7 +- src/conftest/Makefile.am | 2 - src/conftest/Makefile.in | 5 +- src/conftest/conftest.c | 8 - src/conftest/conftest.h | 1 - src/dumm/Makefile.in | 2 + src/include/Makefile.in | 2 + src/ipsec/Makefile.in | 2 + src/ipsec/_ipsec.8 | 2 +- src/ipsec/_ipsec.in | 9 +- src/libcharon/Android.mk | 20 +- src/libcharon/Makefile.am | 42 +- src/libcharon/Makefile.in | 339 ++- src/libcharon/attributes/attributes.c | 16 +- src/libcharon/attributes/attributes.h | 3 + src/libcharon/attributes/mem_pool.c | 1 - src/libcharon/bus/listeners/custom_logger.h | 65 + src/libcharon/config/child_cfg.c | 54 +- src/libcharon/config/child_cfg.h | 10 +- src/libcharon/config/ike_cfg.c | 24 +- src/libcharon/config/peer_cfg.c | 157 +- src/libcharon/config/peer_cfg.h | 16 +- src/libcharon/config/proposal.c | 180 +- src/libcharon/daemon.c | 278 +- src/libcharon/daemon.h | 53 +- src/libcharon/encoding/message.c | 12 +- .../encoding/payloads/configuration_attribute.c | 9 + src/libcharon/kernel/kernel_handler.c | 7 +- src/libcharon/kernel/kernel_handler.h | 2 +- src/libcharon/kernel/kernel_interface.c | 1085 +++++++ src/libcharon/kernel/kernel_interface.h | 655 +++++ src/libcharon/kernel/kernel_ipsec.c | 36 + src/libcharon/kernel/kernel_ipsec.h | 297 ++ src/libcharon/kernel/kernel_listener.h | 107 + src/libcharon/kernel/kernel_net.c | 36 + src/libcharon/kernel/kernel_net.h | 196 ++ src/libcharon/network/receiver.c | 6 +- src/libcharon/plugins/addrblock/Makefile.am | 1 - src/libcharon/plugins/addrblock/Makefile.in | 3 +- src/libcharon/plugins/android_dns/Makefile.am | 1 - src/libcharon/plugins/android_dns/Makefile.in | 3 +- src/libcharon/plugins/android_log/Makefile.am | 1 - src/libcharon/plugins/android_log/Makefile.in | 3 +- src/libcharon/plugins/attr/Makefile.am | 1 - src/libcharon/plugins/attr/Makefile.in | 3 +- src/libcharon/plugins/attr/attr_provider.c | 67 +- src/libcharon/plugins/attr_sql/Makefile.am | 1 - src/libcharon/plugins/attr_sql/Makefile.in | 3 +- src/libcharon/plugins/certexpire/Makefile.am | 1 - src/libcharon/plugins/certexpire/Makefile.in | 3 +- src/libcharon/plugins/connmark/Makefile.am | 1 - src/libcharon/plugins/connmark/Makefile.in | 3 +- src/libcharon/plugins/connmark/connmark_listener.c | 354 ++- src/libcharon/plugins/coupling/Makefile.am | 1 - src/libcharon/plugins/coupling/Makefile.in | 3 +- src/libcharon/plugins/dhcp/Makefile.am | 1 - src/libcharon/plugins/dhcp/Makefile.in | 3 +- src/libcharon/plugins/dhcp/dhcp_socket.c | 4 +- src/libcharon/plugins/dnscert/Makefile.am | 1 - src/libcharon/plugins/dnscert/Makefile.in | 3 +- src/libcharon/plugins/duplicheck/Makefile.am | 1 - src/libcharon/plugins/duplicheck/Makefile.in | 3 +- src/libcharon/plugins/duplicheck/duplicheck.c | 2 + src/libcharon/plugins/eap_aka/Makefile.am | 1 - src/libcharon/plugins/eap_aka/Makefile.in | 3 +- src/libcharon/plugins/eap_aka_3gpp2/Makefile.am | 1 - src/libcharon/plugins/eap_aka_3gpp2/Makefile.in | 3 +- src/libcharon/plugins/eap_dynamic/Makefile.am | 1 - src/libcharon/plugins/eap_dynamic/Makefile.in | 3 +- src/libcharon/plugins/eap_gtc/Makefile.am | 1 - src/libcharon/plugins/eap_gtc/Makefile.in | 3 +- src/libcharon/plugins/eap_identity/Makefile.am | 1 - src/libcharon/plugins/eap_identity/Makefile.in | 3 +- src/libcharon/plugins/eap_md5/Makefile.am | 1 - src/libcharon/plugins/eap_md5/Makefile.in | 3 +- src/libcharon/plugins/eap_mschapv2/Makefile.am | 1 - src/libcharon/plugins/eap_mschapv2/Makefile.in | 3 +- src/libcharon/plugins/eap_peap/Makefile.am | 1 - src/libcharon/plugins/eap_peap/Makefile.in | 3 +- src/libcharon/plugins/eap_radius/Makefile.am | 1 - src/libcharon/plugins/eap_radius/Makefile.in | 3 +- src/libcharon/plugins/eap_sim/Makefile.am | 1 - src/libcharon/plugins/eap_sim/Makefile.in | 3 +- src/libcharon/plugins/eap_sim_file/Makefile.am | 1 - src/libcharon/plugins/eap_sim_file/Makefile.in | 3 +- src/libcharon/plugins/eap_sim_pcsc/Makefile.am | 1 - src/libcharon/plugins/eap_sim_pcsc/Makefile.in | 3 +- .../plugins/eap_simaka_pseudonym/Makefile.am | 1 - .../plugins/eap_simaka_pseudonym/Makefile.in | 3 +- .../plugins/eap_simaka_reauth/Makefile.am | 1 - .../plugins/eap_simaka_reauth/Makefile.in | 3 +- src/libcharon/plugins/eap_simaka_sql/Makefile.am | 1 - src/libcharon/plugins/eap_simaka_sql/Makefile.in | 3 +- src/libcharon/plugins/eap_tls/Makefile.am | 1 - src/libcharon/plugins/eap_tls/Makefile.in | 3 +- src/libcharon/plugins/eap_tnc/Makefile.am | 1 - src/libcharon/plugins/eap_tnc/Makefile.in | 3 +- src/libcharon/plugins/eap_tnc/eap_tnc.c | 2 +- src/libcharon/plugins/eap_ttls/Makefile.am | 1 - src/libcharon/plugins/eap_ttls/Makefile.in | 3 +- src/libcharon/plugins/error_notify/Makefile.am | 1 - src/libcharon/plugins/error_notify/Makefile.in | 3 +- src/libcharon/plugins/ext_auth/Makefile.am | 1 - src/libcharon/plugins/ext_auth/Makefile.in | 3 +- src/libcharon/plugins/farp/Makefile.am | 1 - src/libcharon/plugins/farp/Makefile.in | 3 +- src/libcharon/plugins/forecast/Makefile.am | 1 - src/libcharon/plugins/forecast/Makefile.in | 3 +- .../plugins/forecast/forecast_forwarder.c | 8 +- src/libcharon/plugins/forecast/forecast_listener.c | 252 +- src/libcharon/plugins/ha/Makefile.am | 1 - src/libcharon/plugins/ha/Makefile.in | 3 +- src/libcharon/plugins/ha/ha_child.c | 4 + src/libcharon/plugins/ha/ha_dispatcher.c | 17 +- src/libcharon/plugins/ha/ha_ike.c | 32 +- src/libcharon/plugins/ha/ha_message.c | 2 + src/libcharon/plugins/ha/ha_message.h | 2 + src/libcharon/plugins/ipseckey/Makefile.am | 1 - src/libcharon/plugins/ipseckey/Makefile.in | 3 +- src/libcharon/plugins/kernel_iph/Makefile.am | 1 - src/libcharon/plugins/kernel_iph/Makefile.in | 3 +- src/libcharon/plugins/kernel_iph/kernel_iph_net.c | 4 +- .../plugins/kernel_iph/kernel_iph_plugin.c | 2 - src/libcharon/plugins/kernel_libipsec/Makefile.am | 1 - src/libcharon/plugins/kernel_libipsec/Makefile.in | 3 +- .../kernel_libipsec/kernel_libipsec_ipsec.c | 63 +- .../kernel_libipsec/kernel_libipsec_router.c | 7 +- src/libcharon/plugins/kernel_netlink/Makefile.am | 44 + src/libcharon/plugins/kernel_netlink/Makefile.in | 1007 +++++++ .../plugins/kernel_netlink/kernel_netlink_ipsec.c | 2975 +++++++++++++++++++ .../plugins/kernel_netlink/kernel_netlink_ipsec.h | 46 + .../plugins/kernel_netlink/kernel_netlink_net.c | 2686 +++++++++++++++++ .../plugins/kernel_netlink/kernel_netlink_net.h | 46 + .../plugins/kernel_netlink/kernel_netlink_plugin.c | 85 + .../plugins/kernel_netlink/kernel_netlink_plugin.h | 42 + .../plugins/kernel_netlink/kernel_netlink_shared.c | 655 +++++ .../plugins/kernel_netlink/kernel_netlink_shared.h | 104 + .../plugins/kernel_netlink/suites/test_socket.c | 302 ++ src/libcharon/plugins/kernel_netlink/tests.c | 47 + src/libcharon/plugins/kernel_netlink/tests.h | 16 + src/libcharon/plugins/kernel_pfkey/Makefile.am | 19 + src/libcharon/plugins/kernel_pfkey/Makefile.in | 782 +++++ .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 3094 +++++++++++++++++++ .../plugins/kernel_pfkey/kernel_pfkey_ipsec.h | 46 + .../plugins/kernel_pfkey/kernel_pfkey_plugin.c | 80 + .../plugins/kernel_pfkey/kernel_pfkey_plugin.h | 42 + src/libcharon/plugins/kernel_pfroute/Makefile.am | 19 + src/libcharon/plugins/kernel_pfroute/Makefile.in | 782 +++++ .../plugins/kernel_pfroute/kernel_pfroute_net.c | 1902 ++++++++++++ .../plugins/kernel_pfroute/kernel_pfroute_net.h | 46 + .../plugins/kernel_pfroute/kernel_pfroute_plugin.c | 74 + .../plugins/kernel_pfroute/kernel_pfroute_plugin.h | 42 + src/libcharon/plugins/kernel_wfp/Makefile.am | 1 - src/libcharon/plugins/kernel_wfp/Makefile.in | 3 +- .../plugins/kernel_wfp/kernel_wfp_ipsec.c | 25 +- src/libcharon/plugins/led/Makefile.am | 1 - src/libcharon/plugins/led/Makefile.in | 3 +- src/libcharon/plugins/load_tester/Makefile.am | 1 - src/libcharon/plugins/load_tester/Makefile.in | 3 +- .../plugins/load_tester/load_tester_config.c | 13 +- .../plugins/load_tester/load_tester_plugin.c | 22 +- src/libcharon/plugins/lookip/Makefile.am | 1 - src/libcharon/plugins/lookip/Makefile.in | 3 +- src/libcharon/plugins/maemo/Makefile.am | 1 - src/libcharon/plugins/maemo/Makefile.in | 3 +- src/libcharon/plugins/medcli/Makefile.am | 1 - src/libcharon/plugins/medcli/Makefile.in | 3 +- src/libcharon/plugins/medsrv/Makefile.am | 1 - src/libcharon/plugins/medsrv/Makefile.in | 3 +- src/libcharon/plugins/osx_attr/Makefile.am | 1 - src/libcharon/plugins/osx_attr/Makefile.in | 3 +- src/libcharon/plugins/p_cscf/Makefile.am | 19 + src/libcharon/plugins/p_cscf/Makefile.in | 782 +++++ src/libcharon/plugins/p_cscf/p_cscf_handler.c | 173 ++ src/libcharon/plugins/p_cscf/p_cscf_handler.h | 49 + src/libcharon/plugins/p_cscf/p_cscf_plugin.c | 101 + src/libcharon/plugins/p_cscf/p_cscf_plugin.h | 43 + src/libcharon/plugins/radattr/Makefile.am | 1 - src/libcharon/plugins/radattr/Makefile.in | 3 +- src/libcharon/plugins/resolve/Makefile.am | 1 - src/libcharon/plugins/resolve/Makefile.in | 3 +- src/libcharon/plugins/resolve/resolve_handler.c | 1 - src/libcharon/plugins/smp/Makefile.am | 1 - src/libcharon/plugins/smp/Makefile.in | 3 +- src/libcharon/plugins/smp/smp.c | 8 +- src/libcharon/plugins/socket_default/Makefile.am | 1 - src/libcharon/plugins/socket_default/Makefile.in | 3 +- .../plugins/socket_default/socket_default_socket.c | 8 +- src/libcharon/plugins/socket_dynamic/Makefile.am | 1 - src/libcharon/plugins/socket_dynamic/Makefile.in | 3 +- .../plugins/socket_dynamic/socket_dynamic_socket.c | 7 +- src/libcharon/plugins/socket_win/Makefile.am | 1 - src/libcharon/plugins/socket_win/Makefile.in | 3 +- .../plugins/socket_win/socket_win_socket.c | 7 +- src/libcharon/plugins/sql/Makefile.am | 1 - src/libcharon/plugins/sql/Makefile.in | 3 +- src/libcharon/plugins/stroke/Makefile.am | 1 - src/libcharon/plugins/stroke/Makefile.in | 3 +- src/libcharon/plugins/stroke/stroke_config.c | 123 +- src/libcharon/plugins/stroke/stroke_control.c | 1 - src/libcharon/plugins/stroke/stroke_list.c | 619 +--- src/libcharon/plugins/stroke/stroke_socket.c | 13 +- src/libcharon/plugins/systime_fix/Makefile.am | 1 - src/libcharon/plugins/systime_fix/Makefile.in | 3 +- src/libcharon/plugins/tnc_ifmap/Makefile.am | 1 - src/libcharon/plugins/tnc_ifmap/Makefile.in | 3 +- .../plugins/tnc_ifmap/tnc_ifmap_listener.c | 5 +- src/libcharon/plugins/tnc_pdp/Makefile.am | 1 - src/libcharon/plugins/tnc_pdp/Makefile.in | 3 +- src/libcharon/plugins/uci/Makefile.am | 1 - src/libcharon/plugins/uci/Makefile.in | 3 +- src/libcharon/plugins/unity/Makefile.am | 1 - src/libcharon/plugins/unity/Makefile.in | 3 +- src/libcharon/plugins/updown/Makefile.am | 1 - src/libcharon/plugins/updown/Makefile.in | 3 +- src/libcharon/plugins/updown/updown_listener.c | 70 +- src/libcharon/plugins/vici/Makefile.am | 8 +- src/libcharon/plugins/vici/Makefile.in | 22 +- src/libcharon/plugins/vici/README.md | 98 +- src/libcharon/plugins/vici/perl/Makefile.am | 27 + src/libcharon/plugins/vici/perl/Makefile.in | 567 ++++ .../plugins/vici/perl/Vici-Session/Changes | 6 + .../plugins/vici/perl/Vici-Session/MANIFEST | 9 + .../plugins/vici/perl/Vici-Session/Makefile.PL | 11 + .../plugins/vici/perl/Vici-Session/README.pod | 649 ++++ .../vici/perl/Vici-Session/lib/Vici/Message.pm | 256 ++ .../vici/perl/Vici-Session/lib/Vici/Packet.pm | 191 ++ .../vici/perl/Vici-Session/lib/Vici/Session.pm | 204 ++ .../vici/perl/Vici-Session/lib/Vici/Transport.pm | 88 + .../vici/perl/Vici-Session/t/Vici-Session.t | 18 + src/libcharon/plugins/vici/python/Makefile.in | 2 + src/libcharon/plugins/vici/python/vici/session.py | 8 + src/libcharon/plugins/vici/ruby/Makefile.in | 2 + src/libcharon/plugins/vici/ruby/lib/vici.rb | 6 + src/libcharon/plugins/vici/vici_cert_info.c | 57 + src/libcharon/plugins/vici/vici_cert_info.h | 32 + src/libcharon/plugins/vici/vici_config.c | 359 ++- src/libcharon/plugins/vici/vici_config.h | 5 +- src/libcharon/plugins/vici/vici_control.c | 187 +- src/libcharon/plugins/vici/vici_cred.c | 69 +- src/libcharon/plugins/vici/vici_plugin.c | 3 +- src/libcharon/plugins/vici/vici_query.c | 374 ++- src/libcharon/plugins/vici/vici_tests.c | 1 - src/libcharon/plugins/whitelist/Makefile.am | 1 - src/libcharon/plugins/whitelist/Makefile.in | 3 +- src/libcharon/plugins/xauth_eap/Makefile.am | 1 - src/libcharon/plugins/xauth_eap/Makefile.in | 3 +- src/libcharon/plugins/xauth_generic/Makefile.am | 1 - src/libcharon/plugins/xauth_generic/Makefile.in | 3 +- src/libcharon/plugins/xauth_noauth/Makefile.am | 1 - src/libcharon/plugins/xauth_noauth/Makefile.in | 3 +- src/libcharon/plugins/xauth_pam/Makefile.am | 1 - src/libcharon/plugins/xauth_pam/Makefile.in | 3 +- src/libcharon/processing/jobs/adopt_children_job.c | 1 - src/libcharon/processing/jobs/redirect_job.c | 106 + src/libcharon/processing/jobs/redirect_job.h | 51 + src/libcharon/processing/jobs/send_keepalive_job.c | 2 +- src/libcharon/sa/child_sa.c | 82 +- src/libcharon/sa/ike_sa.c | 557 +++- src/libcharon/sa/ike_sa.h | 65 +- src/libcharon/sa/ike_sa_manager.c | 97 +- .../ikev1/authenticators/pubkey_v1_authenticator.c | 4 +- src/libcharon/sa/ikev1/phase1.c | 2 +- src/libcharon/sa/ikev1/tasks/isakmp_natd.c | 3 +- src/libcharon/sa/ikev1/tasks/mode_config.c | 37 +- src/libcharon/sa/ikev1/tasks/quick_mode.c | 18 +- src/libcharon/sa/ikev1/tasks/xauth.c | 1 - .../sa/ikev2/authenticators/pubkey_authenticator.c | 23 +- src/libcharon/sa/ikev2/task_manager_v2.c | 102 +- src/libcharon/sa/ikev2/tasks/child_create.c | 7 +- src/libcharon/sa/ikev2/tasks/child_rekey.c | 11 +- src/libcharon/sa/ikev2/tasks/ike_auth.c | 144 +- src/libcharon/sa/ikev2/tasks/ike_config.c | 5 + src/libcharon/sa/ikev2/tasks/ike_init.c | 146 +- src/libcharon/sa/ikev2/tasks/ike_me.c | 5 +- src/libcharon/sa/ikev2/tasks/ike_mobike.c | 13 +- src/libcharon/sa/ikev2/tasks/ike_natd.c | 9 +- src/libcharon/sa/ikev2/tasks/ike_redirect.c | 150 + src/libcharon/sa/ikev2/tasks/ike_redirect.h | 54 + src/libcharon/sa/ikev2/tasks/ike_vendor.c | 56 +- .../sa/ikev2/tasks/ike_verify_peer_cert.c | 117 + .../sa/ikev2/tasks/ike_verify_peer_cert.h | 54 + src/libcharon/sa/redirect_manager.c | 274 ++ src/libcharon/sa/redirect_manager.h | 109 + src/libcharon/sa/redirect_provider.h | 59 + src/libcharon/sa/shunt_manager.c | 25 +- src/libcharon/sa/task.c | 2 + src/libcharon/sa/task.h | 18 +- src/libcharon/sa/trap_manager.c | 4 +- src/libcharon/tests/Makefile.am | 2 - src/libcharon/tests/Makefile.in | 5 +- src/libcharon/tests/libcharon_tests.c | 3 - src/libfast/Makefile.in | 2 + src/libhydra/Android.mk | 37 - src/libhydra/Makefile.am | 60 - src/libhydra/Makefile.in | 922 ------ src/libhydra/hydra.c | 93 - src/libhydra/hydra.h | 71 - src/libhydra/kernel/kernel_interface.c | 1086 ------- src/libhydra/kernel/kernel_interface.h | 655 ----- src/libhydra/kernel/kernel_ipsec.c | 38 - src/libhydra/kernel/kernel_ipsec.h | 297 -- src/libhydra/kernel/kernel_listener.h | 107 - src/libhydra/kernel/kernel_net.c | 38 - src/libhydra/kernel/kernel_net.h | 196 -- src/libhydra/plugins/kernel_netlink/Makefile.am | 44 - src/libhydra/plugins/kernel_netlink/Makefile.in | 1005 ------- .../plugins/kernel_netlink/kernel_netlink_ipsec.c | 2966 ------------------- .../plugins/kernel_netlink/kernel_netlink_ipsec.h | 46 - .../plugins/kernel_netlink/kernel_netlink_net.c | 2685 ----------------- .../plugins/kernel_netlink/kernel_netlink_net.h | 46 - .../plugins/kernel_netlink/kernel_netlink_plugin.c | 87 - .../plugins/kernel_netlink/kernel_netlink_plugin.h | 42 - .../plugins/kernel_netlink/kernel_netlink_shared.c | 655 ----- .../plugins/kernel_netlink/kernel_netlink_shared.h | 96 - .../plugins/kernel_netlink/suites/test_socket.c | 302 -- src/libhydra/plugins/kernel_netlink/tests.c | 49 - src/libhydra/plugins/kernel_netlink/tests.h | 16 - src/libhydra/plugins/kernel_pfkey/Makefile.am | 19 - src/libhydra/plugins/kernel_pfkey/Makefile.in | 780 ----- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 3102 -------------------- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.h | 46 - .../plugins/kernel_pfkey/kernel_pfkey_plugin.c | 82 - .../plugins/kernel_pfkey/kernel_pfkey_plugin.h | 42 - src/libhydra/plugins/kernel_pfroute/Makefile.am | 19 - src/libhydra/plugins/kernel_pfroute/Makefile.in | 780 ----- .../plugins/kernel_pfroute/kernel_pfroute_net.c | 1903 ------------ .../plugins/kernel_pfroute/kernel_pfroute_net.h | 46 - .../plugins/kernel_pfroute/kernel_pfroute_plugin.c | 76 - .../plugins/kernel_pfroute/kernel_pfroute_plugin.h | 42 - src/libhydra/tests/Makefile.am | 18 - src/libhydra/tests/Makefile.in | 839 ------ src/libhydra/tests/hydra_tests.c | 53 - src/libhydra/tests/hydra_tests.h | 14 - src/libimcv/Makefile.in | 2 + src/libimcv/imc/imc_os_info.c | 12 +- src/libimcv/plugins/imc_attestation/Makefile.in | 2 + src/libimcv/plugins/imc_hcd/Makefile.in | 2 + src/libimcv/plugins/imc_os/Makefile.in | 2 + src/libimcv/plugins/imc_scanner/Makefile.in | 2 + src/libimcv/plugins/imc_swid/Makefile.in | 2 + src/libimcv/plugins/imc_test/Makefile.in | 2 + src/libimcv/plugins/imv_attestation/Makefile.in | 2 + .../imv_attestation/imv_attestation_agent.c | 6 +- .../imv_attestation/imv_attestation_state.h | 2 +- src/libimcv/plugins/imv_hcd/Makefile.in | 2 + src/libimcv/plugins/imv_os/Makefile.in | 2 + src/libimcv/plugins/imv_scanner/Makefile.in | 2 + src/libimcv/plugins/imv_swid/Makefile.in | 2 + src/libimcv/plugins/imv_swid/imv_swid_agent.c | 11 +- src/libimcv/plugins/imv_swid/imv_swid_state.c | 19 +- src/libimcv/plugins/imv_swid/imv_swid_state.h | 37 +- src/libimcv/plugins/imv_test/Makefile.in | 2 + src/libimcv/pts/components/pts_component_manager.h | 4 +- src/libipsec/Makefile.in | 2 + src/libipsec/ipsec_policy_mgr.c | 11 +- src/libipsec/ipsec_policy_mgr.h | 11 +- src/libipsec/tests/Makefile.in | 2 + src/libpttls/Makefile.in | 2 + src/libradius/Makefile.in | 2 + src/libsimaka/Makefile.am | 1 - src/libsimaka/Makefile.in | 3 +- src/libstrongswan/Android.mk | 3 +- src/libstrongswan/Makefile.am | 4 +- src/libstrongswan/Makefile.in | 18 + src/libstrongswan/asn1/asn1.h | 1 + src/libstrongswan/asn1/oid.c | 889 +++--- src/libstrongswan/asn1/oid.h | 429 +-- src/libstrongswan/asn1/oid.txt | 1 + src/libstrongswan/collections/array.c | 10 + src/libstrongswan/collections/array.h | 15 + src/libstrongswan/collections/linked_list.c | 54 +- src/libstrongswan/collections/linked_list.h | 23 +- src/libstrongswan/credentials/auth_cfg.c | 248 +- src/libstrongswan/credentials/auth_cfg.h | 13 + .../credentials/certificates/certificate.c | 9 +- .../credentials/certificates/certificate_printer.c | 753 +++++ .../credentials/certificates/certificate_printer.h | 70 + .../credentials/certificates/ocsp_response.h | 7 + src/libstrongswan/credentials/certificates/x509.c | 27 + src/libstrongswan/credentials/certificates/x509.h | 4 + src/libstrongswan/credentials/credential_manager.c | 8 +- src/libstrongswan/credentials/credential_manager.h | 7 +- src/libstrongswan/library.c | 33 +- src/libstrongswan/library.h | 12 +- src/libstrongswan/plugins/acert/Makefile.in | 2 + src/libstrongswan/plugins/aes/Makefile.in | 2 + src/libstrongswan/plugins/aesni/Makefile.in | 2 + src/libstrongswan/plugins/af_alg/Makefile.in | 2 + src/libstrongswan/plugins/agent/Makefile.in | 2 + src/libstrongswan/plugins/bliss/Makefile.in | 2 + src/libstrongswan/plugins/bliss/tests/Makefile.in | 2 + src/libstrongswan/plugins/blowfish/Makefile.in | 2 + src/libstrongswan/plugins/ccm/Makefile.in | 2 + src/libstrongswan/plugins/chapoly/Makefile.in | 2 + .../plugins/chapoly/chapoly_drv_portable.c | 21 - src/libstrongswan/plugins/cmac/Makefile.in | 2 + src/libstrongswan/plugins/constraints/Makefile.in | 2 + src/libstrongswan/plugins/ctr/Makefile.in | 2 + src/libstrongswan/plugins/curl/Makefile.in | 2 + src/libstrongswan/plugins/des/Makefile.in | 2 + src/libstrongswan/plugins/dnskey/Makefile.in | 2 + src/libstrongswan/plugins/files/Makefile.in | 2 + src/libstrongswan/plugins/fips_prf/Makefile.in | 2 + src/libstrongswan/plugins/gcm/Makefile.in | 2 + src/libstrongswan/plugins/gcrypt/Makefile.in | 2 + src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c | 8 +- src/libstrongswan/plugins/gmp/Makefile.in | 2 + src/libstrongswan/plugins/gmp/gmp_plugin.c | 16 +- src/libstrongswan/plugins/hmac/Makefile.in | 2 + src/libstrongswan/plugins/keychain/Makefile.in | 2 + src/libstrongswan/plugins/ldap/Makefile.in | 2 + src/libstrongswan/plugins/md4/Makefile.in | 2 + src/libstrongswan/plugins/md5/Makefile.in | 2 + src/libstrongswan/plugins/mysql/Makefile.in | 2 + src/libstrongswan/plugins/nonce/Makefile.in | 2 + src/libstrongswan/plugins/ntru/Makefile.in | 2 + src/libstrongswan/plugins/openssl/Makefile.in | 2 + src/libstrongswan/plugins/openssl/openssl_plugin.c | 46 +- src/libstrongswan/plugins/padlock/Makefile.in | 2 + src/libstrongswan/plugins/pem/Makefile.in | 2 + src/libstrongswan/plugins/pgp/Makefile.in | 2 + src/libstrongswan/plugins/pkcs1/Makefile.in | 2 + src/libstrongswan/plugins/pkcs11/Makefile.in | 2 + src/libstrongswan/plugins/pkcs12/Makefile.in | 2 + src/libstrongswan/plugins/pkcs7/Makefile.in | 2 + src/libstrongswan/plugins/pkcs8/Makefile.in | 2 + src/libstrongswan/plugins/pubkey/Makefile.in | 2 + src/libstrongswan/plugins/pubkey/pubkey_cert.c | 8 + src/libstrongswan/plugins/pubkey/pubkey_cert.h | 7 + src/libstrongswan/plugins/random/Makefile.in | 2 + src/libstrongswan/plugins/rc2/Makefile.in | 2 + src/libstrongswan/plugins/rdrand/Makefile.in | 2 + src/libstrongswan/plugins/revocation/Makefile.in | 2 + src/libstrongswan/plugins/sha1/Makefile.in | 2 + src/libstrongswan/plugins/sha2/Makefile.in | 2 + src/libstrongswan/plugins/sha3/Makefile.in | 2 + src/libstrongswan/plugins/soup/Makefile.in | 2 + src/libstrongswan/plugins/sqlite/Makefile.in | 2 + src/libstrongswan/plugins/sshkey/Makefile.in | 2 + src/libstrongswan/plugins/test_vectors/Makefile.in | 2 + src/libstrongswan/plugins/unbound/Makefile.in | 2 + src/libstrongswan/plugins/winhttp/Makefile.in | 2 + src/libstrongswan/plugins/x509/Makefile.in | 2 + src/libstrongswan/plugins/x509/x509_cert.c | 4 +- .../plugins/x509/x509_ocsp_response.c | 42 +- src/libstrongswan/plugins/xcbc/Makefile.in | 2 + src/libstrongswan/processing/watcher.c | 7 + src/libstrongswan/tests/Makefile.am | 1 + src/libstrongswan/tests/Makefile.in | 21 + src/libstrongswan/tests/suites/test_array.c | 43 + src/libstrongswan/tests/suites/test_auth_cfg.c | 122 + .../tests/suites/test_identification.c | 261 +- src/libstrongswan/tests/suites/test_linked_list.c | 91 + src/libstrongswan/tests/tests.h | 1 + src/libstrongswan/threading/thread.c | 34 +- src/libstrongswan/threading/thread.h | 8 +- src/libstrongswan/threading/windows/thread.c | 4 + src/libstrongswan/utils/compat/windows.c | 1 - src/libstrongswan/utils/debug.c | 6 +- src/libstrongswan/utils/identification.c | 389 ++- src/libstrongswan/utils/identification.h | 2 + src/libstrongswan/utils/utils/byteorder.h | 78 +- src/libtls/Makefile.in | 2 + src/libtls/tests/Makefile.in | 2 + src/libtls/tls_peer.c | 3 +- src/libtls/tls_server.c | 2 +- src/libtnccs/Makefile.in | 2 + src/libtnccs/plugins/tnc_imc/Makefile.in | 2 + src/libtnccs/plugins/tnc_imv/Makefile.in | 2 + src/libtnccs/plugins/tnc_tnccs/Makefile.in | 2 + src/libtnccs/plugins/tnccs_11/Makefile.in | 2 + src/libtnccs/plugins/tnccs_20/Makefile.in | 2 + src/libtnccs/plugins/tnccs_20/tnccs_20.c | 38 +- src/libtnccs/plugins/tnccs_dynamic/Makefile.in | 2 + src/libtncif/Makefile.in | 2 + src/manager/Makefile.in | 2 + src/medsrv/Makefile.in | 2 + src/pki/Makefile.am | 5 +- src/pki/Makefile.in | 12 +- src/pki/command.c | 11 +- src/pki/command.h | 2 +- src/pki/commands/print.c | 543 +--- src/pki/man/Makefile.in | 2 + src/pool/Makefile.am | 2 - src/pool/Makefile.in | 5 +- src/pt-tls-client/Makefile.in | 2 + src/scepclient/Makefile.am | 1 - src/scepclient/Makefile.in | 3 +- src/starter/Android.mk | 3 +- src/starter/Makefile.am | 4 +- src/starter/Makefile.in | 8 +- src/starter/confread.c | 4 +- src/starter/netkey.c | 1 - src/starter/starter.c | 4 - src/starter/tests/Makefile.in | 2 + src/stroke/Makefile.in | 2 + src/stroke/stroke.c | 13 +- src/swanctl/Makefile.am | 8 +- src/swanctl/Makefile.in | 28 +- src/swanctl/command.c | 11 +- src/swanctl/command.h | 4 +- src/swanctl/commands/list_algs.c | 104 + src/swanctl/commands/list_certs.c | 603 +--- src/swanctl/commands/list_sas.c | 13 +- src/swanctl/commands/load_conns.c | 9 +- src/swanctl/commands/load_creds.c | 47 +- src/swanctl/commands/redirect.c | 132 + src/swanctl/commands/stats.c | 12 + src/swanctl/swanctl.8.in | 9 +- src/swanctl/swanctl.conf | 22 +- src/swanctl/swanctl.conf.5.main | 139 +- src/swanctl/swanctl.h | 18 + src/swanctl/swanctl.opt | 99 +- 543 files changed, 29579 insertions(+), 23917 deletions(-) create mode 100644 src/libcharon/bus/listeners/custom_logger.h create mode 100644 src/libcharon/kernel/kernel_interface.c create mode 100644 src/libcharon/kernel/kernel_interface.h create mode 100644 src/libcharon/kernel/kernel_ipsec.c create mode 100644 src/libcharon/kernel/kernel_ipsec.h create mode 100644 src/libcharon/kernel/kernel_listener.h create mode 100644 src/libcharon/kernel/kernel_net.c create mode 100644 src/libcharon/kernel/kernel_net.h create mode 100644 src/libcharon/plugins/kernel_netlink/Makefile.am create mode 100644 src/libcharon/plugins/kernel_netlink/Makefile.in create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c create mode 100644 src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h create mode 100644 src/libcharon/plugins/kernel_netlink/suites/test_socket.c create mode 100644 src/libcharon/plugins/kernel_netlink/tests.c create mode 100644 src/libcharon/plugins/kernel_netlink/tests.h create mode 100644 src/libcharon/plugins/kernel_pfkey/Makefile.am create mode 100644 src/libcharon/plugins/kernel_pfkey/Makefile.in create mode 100644 src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c create mode 100644 src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h create mode 100644 src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c create mode 100644 src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h create mode 100644 src/libcharon/plugins/kernel_pfroute/Makefile.am create mode 100644 src/libcharon/plugins/kernel_pfroute/Makefile.in create mode 100644 src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c create mode 100644 src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h create mode 100644 src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c create mode 100644 src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h create mode 100644 src/libcharon/plugins/p_cscf/Makefile.am create mode 100644 src/libcharon/plugins/p_cscf/Makefile.in create mode 100644 src/libcharon/plugins/p_cscf/p_cscf_handler.c create mode 100644 src/libcharon/plugins/p_cscf/p_cscf_handler.h create mode 100644 src/libcharon/plugins/p_cscf/p_cscf_plugin.c create mode 100644 src/libcharon/plugins/p_cscf/p_cscf_plugin.h create mode 100644 src/libcharon/plugins/vici/perl/Makefile.am create mode 100644 src/libcharon/plugins/vici/perl/Makefile.in create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/Changes create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/MANIFEST create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/Makefile.PL create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/README.pod create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Message.pm create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Packet.pm create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Transport.pm create mode 100644 src/libcharon/plugins/vici/perl/Vici-Session/t/Vici-Session.t create mode 100644 src/libcharon/plugins/vici/vici_cert_info.c create mode 100644 src/libcharon/plugins/vici/vici_cert_info.h create mode 100644 src/libcharon/processing/jobs/redirect_job.c create mode 100644 src/libcharon/processing/jobs/redirect_job.h create mode 100644 src/libcharon/sa/ikev2/tasks/ike_redirect.c create mode 100644 src/libcharon/sa/ikev2/tasks/ike_redirect.h create mode 100644 src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.c create mode 100644 src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.h create mode 100644 src/libcharon/sa/redirect_manager.c create mode 100644 src/libcharon/sa/redirect_manager.h create mode 100644 src/libcharon/sa/redirect_provider.h delete mode 100644 src/libhydra/Android.mk delete mode 100644 src/libhydra/Makefile.am delete mode 100644 src/libhydra/Makefile.in delete mode 100644 src/libhydra/hydra.c delete mode 100644 src/libhydra/hydra.h delete mode 100644 src/libhydra/kernel/kernel_interface.c delete mode 100644 src/libhydra/kernel/kernel_interface.h delete mode 100644 src/libhydra/kernel/kernel_ipsec.c delete mode 100644 src/libhydra/kernel/kernel_ipsec.h delete mode 100644 src/libhydra/kernel/kernel_listener.h delete mode 100644 src/libhydra/kernel/kernel_net.c delete mode 100644 src/libhydra/kernel/kernel_net.h delete mode 100644 src/libhydra/plugins/kernel_netlink/Makefile.am delete mode 100644 src/libhydra/plugins/kernel_netlink/Makefile.in delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.h delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_net.h delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.h delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c delete mode 100644 src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h delete mode 100644 src/libhydra/plugins/kernel_netlink/suites/test_socket.c delete mode 100644 src/libhydra/plugins/kernel_netlink/tests.c delete mode 100644 src/libhydra/plugins/kernel_netlink/tests.h delete mode 100644 src/libhydra/plugins/kernel_pfkey/Makefile.am delete mode 100644 src/libhydra/plugins/kernel_pfkey/Makefile.in delete mode 100644 src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c delete mode 100644 src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.h delete mode 100644 src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c delete mode 100644 src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.h delete mode 100644 src/libhydra/plugins/kernel_pfroute/Makefile.am delete mode 100644 src/libhydra/plugins/kernel_pfroute/Makefile.in delete mode 100644 src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c delete mode 100644 src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.h delete mode 100644 src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c delete mode 100644 src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.h delete mode 100644 src/libhydra/tests/Makefile.am delete mode 100644 src/libhydra/tests/Makefile.in delete mode 100644 src/libhydra/tests/hydra_tests.c delete mode 100644 src/libhydra/tests/hydra_tests.h create mode 100644 src/libstrongswan/credentials/certificates/certificate_printer.c create mode 100644 src/libstrongswan/credentials/certificates/certificate_printer.h create mode 100644 src/libstrongswan/credentials/certificates/x509.c create mode 100644 src/libstrongswan/tests/suites/test_auth_cfg.c create mode 100644 src/swanctl/commands/list_algs.c create mode 100644 src/swanctl/commands/redirect.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 9608a3a13..a9df10cc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,10 +4,6 @@ if USE_LIBSTRONGSWAN SUBDIRS += libstrongswan endif -if USE_LIBHYDRA - SUBDIRS += libhydra -endif - if USE_LIBIPSEC SUBDIRS += libipsec endif diff --git a/src/Makefile.in b/src/Makefile.in index 7596e7e55..1d012fb22 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -78,39 +78,38 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @USE_LIBSTRONGSWAN_TRUE@am__append_1 = libstrongswan -@USE_LIBHYDRA_TRUE@am__append_2 = libhydra -@USE_LIBIPSEC_TRUE@am__append_3 = libipsec -@USE_SIMAKA_TRUE@am__append_4 = libsimaka -@USE_TLS_TRUE@am__append_5 = libtls -@USE_RADIUS_TRUE@am__append_6 = libradius -@USE_LIBTNCIF_TRUE@am__append_7 = libtncif -@USE_LIBTNCCS_TRUE@am__append_8 = libtnccs -@USE_LIBPTTLS_TRUE@am__append_9 = libpttls -@USE_IMCV_TRUE@am__append_10 = libimcv -@USE_LIBCHARON_TRUE@am__append_11 = libcharon -@USE_FILE_CONFIG_TRUE@am__append_12 = starter -@USE_IPSEC_SCRIPT_TRUE@am__append_13 = ipsec _copyright -@USE_CHARON_TRUE@am__append_14 = charon -@USE_SYSTEMD_TRUE@am__append_15 = charon-systemd -@USE_NM_TRUE@am__append_16 = charon-nm -@USE_STROKE_TRUE@am__append_17 = stroke -@USE_UPDOWN_TRUE@am__append_18 = _updown -@USE_SCEPCLIENT_TRUE@am__append_19 = scepclient -@USE_PKI_TRUE@am__append_20 = pki -@USE_SWANCTL_TRUE@am__append_21 = swanctl -@USE_CONFTEST_TRUE@am__append_22 = conftest -@USE_DUMM_TRUE@am__append_23 = dumm -@USE_FAST_TRUE@am__append_24 = libfast -@USE_MANAGER_TRUE@am__append_25 = manager -@USE_MEDSRV_TRUE@am__append_26 = medsrv -@USE_ATTR_SQL_TRUE@am__append_27 = pool -@USE_ATTR_SQL_FALSE@@USE_SQL_TRUE@am__append_28 = pool -@USE_TKM_TRUE@am__append_29 = charon-tkm -@USE_CMD_TRUE@am__append_30 = charon-cmd -@USE_SVC_TRUE@am__append_31 = charon-svc -@USE_LIBPTTLS_TRUE@am__append_32 = pt-tls-client -@USE_INTEGRITY_TEST_TRUE@am__append_33 = checksum -@USE_AIKGEN_TRUE@am__append_34 = aikgen +@USE_LIBIPSEC_TRUE@am__append_2 = libipsec +@USE_SIMAKA_TRUE@am__append_3 = libsimaka +@USE_TLS_TRUE@am__append_4 = libtls +@USE_RADIUS_TRUE@am__append_5 = libradius +@USE_LIBTNCIF_TRUE@am__append_6 = libtncif +@USE_LIBTNCCS_TRUE@am__append_7 = libtnccs +@USE_LIBPTTLS_TRUE@am__append_8 = libpttls +@USE_IMCV_TRUE@am__append_9 = libimcv +@USE_LIBCHARON_TRUE@am__append_10 = libcharon +@USE_FILE_CONFIG_TRUE@am__append_11 = starter +@USE_IPSEC_SCRIPT_TRUE@am__append_12 = ipsec _copyright +@USE_CHARON_TRUE@am__append_13 = charon +@USE_SYSTEMD_TRUE@am__append_14 = charon-systemd +@USE_NM_TRUE@am__append_15 = charon-nm +@USE_STROKE_TRUE@am__append_16 = stroke +@USE_UPDOWN_TRUE@am__append_17 = _updown +@USE_SCEPCLIENT_TRUE@am__append_18 = scepclient +@USE_PKI_TRUE@am__append_19 = pki +@USE_SWANCTL_TRUE@am__append_20 = swanctl +@USE_CONFTEST_TRUE@am__append_21 = conftest +@USE_DUMM_TRUE@am__append_22 = dumm +@USE_FAST_TRUE@am__append_23 = libfast +@USE_MANAGER_TRUE@am__append_24 = manager +@USE_MEDSRV_TRUE@am__append_25 = medsrv +@USE_ATTR_SQL_TRUE@am__append_26 = pool +@USE_ATTR_SQL_FALSE@@USE_SQL_TRUE@am__append_27 = pool +@USE_TKM_TRUE@am__append_28 = charon-tkm +@USE_CMD_TRUE@am__append_29 = charon-cmd +@USE_SVC_TRUE@am__append_30 = charon-svc +@USE_LIBPTTLS_TRUE@am__append_31 = pt-tls-client +@USE_INTEGRITY_TEST_TRUE@am__append_32 = checksum +@USE_AIKGEN_TRUE@am__append_33 = aikgen subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -184,12 +183,12 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = . include libstrongswan libhydra libipsec libsimaka \ - libtls libradius libtncif libtnccs libpttls libimcv libcharon \ - starter ipsec _copyright charon charon-systemd charon-nm \ - stroke _updown scepclient pki swanctl conftest dumm libfast \ - manager medsrv pool charon-tkm charon-cmd charon-svc \ - pt-tls-client checksum aikgen +DIST_SUBDIRS = . include libstrongswan libipsec libsimaka libtls \ + libradius libtncif libtnccs libpttls libimcv libcharon starter \ + ipsec _copyright charon charon-systemd charon-nm stroke \ + _updown scepclient pki swanctl conftest dumm libfast manager \ + medsrv pool charon-tkm charon-cmd charon-svc pt-tls-client \ + checksum aikgen DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -428,6 +427,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -451,8 +452,7 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_22) $(am__append_23) $(am__append_24) \ $(am__append_25) $(am__append_26) $(am__append_27) \ $(am__append_28) $(am__append_29) $(am__append_30) \ - $(am__append_31) $(am__append_32) $(am__append_33) \ - $(am__append_34) + $(am__append_31) $(am__append_32) $(am__append_33) all: all-recursive .SUFFIXES: diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in index 2a4838c9a..432bde59b 100644 --- a/src/_copyright/Makefile.in +++ b/src/_copyright/Makefile.in @@ -382,6 +382,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in index fe31dff64..08fce3e2c 100644 --- a/src/_updown/Makefile.in +++ b/src/_updown/Makefile.in @@ -359,6 +359,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/aikgen/Makefile.in b/src/aikgen/Makefile.in index 33ed13397..8fb9126e5 100644 --- a/src/aikgen/Makefile.in +++ b/src/aikgen/Makefile.in @@ -385,6 +385,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/charon-cmd/Makefile.am b/src/charon-cmd/Makefile.am index 73df45072..1f4033aad 100644 --- a/src/charon-cmd/Makefile.am +++ b/src/charon-cmd/Makefile.am @@ -12,7 +12,6 @@ charon-cmd.o : $(top_builddir)/config.status AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -20,6 +19,5 @@ AM_CPPFLAGS = \ charon_cmd_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/charon-cmd/Makefile.in b/src/charon-cmd/Makefile.in index 64dea34c7..f48410270 100644 --- a/src/charon-cmd/Makefile.in +++ b/src/charon-cmd/Makefile.in @@ -109,7 +109,6 @@ charon_cmd_OBJECTS = $(am_charon_cmd_OBJECTS) am__DEPENDENCIES_1 = charon_cmd_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) @@ -419,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -442,7 +443,6 @@ charon_cmd_SOURCES = \ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -450,7 +450,6 @@ AM_CPPFLAGS = \ charon_cmd_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c index d3b31cc0d..f350198c6 100644 --- a/src/charon-cmd/charon-cmd.c +++ b/src/charon-cmd/charon-cmd.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -330,11 +329,6 @@ int main(int argc, char *argv[]) exit(SS_RC_DAEMON_INTEGRITY); } } - atexit(libhydra_deinit); - if (!libhydra_init()) - { - exit(SS_RC_INITIALIZATION_FAILED); - } atexit(libcharon_deinit); if (!libcharon_init()) { diff --git a/src/charon-nm/Makefile.am b/src/charon-nm/Makefile.am index d3630ffd5..b6f0c8b54 100644 --- a/src/charon-nm/Makefile.am +++ b/src/charon-nm/Makefile.am @@ -9,7 +9,6 @@ charon_nm_SOURCES = \ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -21,6 +20,5 @@ AM_CFLAGS = \ charon_nm_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS} diff --git a/src/charon-nm/Makefile.in b/src/charon-nm/Makefile.in index 82f6fbcb2..490a08023 100644 --- a/src/charon-nm/Makefile.in +++ b/src/charon-nm/Makefile.in @@ -109,7 +109,6 @@ charon_nm_OBJECTS = $(am_charon_nm_OBJECTS) am__DEPENDENCIES_1 = charon_nm_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) @@ -390,6 +389,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -412,7 +413,6 @@ charon_nm_SOURCES = \ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -424,7 +424,6 @@ AM_CFLAGS = \ charon_nm_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS} diff --git a/src/charon-nm/charon-nm.c b/src/charon-nm/charon-nm.c index fb090e5d3..cbbed7ac1 100644 --- a/src/charon-nm/charon-nm.c +++ b/src/charon-nm/charon-nm.c @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -177,14 +176,6 @@ int main(int argc, char *argv[]) exit(SS_RC_DAEMON_INTEGRITY); } - if (!libhydra_init()) - { - dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm"); - libhydra_deinit(); - library_deinit(); - exit(SS_RC_INITIALIZATION_FAILED); - } - if (!libcharon_init()) { dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm"); @@ -212,7 +203,6 @@ int main(int argc, char *argv[]) { DBG1(DBG_DMN, "integrity tests enabled:"); DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests"); - DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests"); DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests"); DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test"); } @@ -260,7 +250,6 @@ int main(int argc, char *argv[]) deinit: libcharon_deinit(); - libhydra_deinit(); library_deinit(); return status; } diff --git a/src/charon-svc/Makefile.am b/src/charon-svc/Makefile.am index ecccf02f5..c91ad08f8 100644 --- a/src/charon-svc/Makefile.am +++ b/src/charon-svc/Makefile.am @@ -6,11 +6,9 @@ charon-svc.o : $(top_builddir)/config.status AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DPLUGINS=\""${charon_plugins}\"" charon_svc_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la diff --git a/src/charon-svc/Makefile.in b/src/charon-svc/Makefile.in index 1c0a4058d..4f9143d9b 100644 --- a/src/charon-svc/Makefile.in +++ b/src/charon-svc/Makefile.in @@ -105,7 +105,6 @@ am_charon_svc_OBJECTS = charon-svc.$(OBJEXT) charon_svc_OBJECTS = $(am_charon_svc_OBJECTS) charon_svc_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -384,6 +383,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -400,13 +401,11 @@ xml_LIBS = @xml_LIBS@ charon_svc_SOURCES = charon-svc.c AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DPLUGINS=\""${charon_plugins}\"" charon_svc_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la all: all-am diff --git a/src/charon-svc/charon-svc.c b/src/charon-svc/charon-svc.c index 03cbdb871..823b366c0 100644 --- a/src/charon-svc/charon-svc.c +++ b/src/charon-svc/charon-svc.c @@ -14,7 +14,6 @@ */ #include -#include #include #include @@ -189,6 +188,15 @@ static int service_wait() return 0; } +/** + * Add namespace alias + */ +static void __attribute__ ((constructor))register_namespace() +{ + /* inherit settings from charon */ + library_add_namespace("charon"); +} + /** * Initialize and run charon using a wait function */ @@ -210,28 +218,22 @@ static void init_and_run(DWORD dwArgc, LPTSTR *lpszArgv, int (*wait)()) if (library_init(NULL, SERVICE_NAME)) { update_status(SERVICE_START_PENDING); - if (libhydra_init()) + if (libcharon_init()) { + charon->load_loggers(charon, levels, TRUE); + print_version(); update_status(SERVICE_START_PENDING); - if (libcharon_init()) + if (charon->initialize(charon, PLUGINS)) { - charon->load_loggers(charon, levels, TRUE); - print_version(); update_status(SERVICE_START_PENDING); - if (charon->initialize(charon, PLUGINS)) - { - update_status(SERVICE_START_PENDING); - lib->plugins->status(lib->plugins, LEVEL_CTRL); + lib->plugins->status(lib->plugins, LEVEL_CTRL); - charon->start(charon); + charon->start(charon); - status.dwWin32ExitCode = wait(); - } - update_status(SERVICE_STOP_PENDING); - libcharon_deinit(); + status.dwWin32ExitCode = wait(); } update_status(SERVICE_STOP_PENDING); - libhydra_deinit(); + libcharon_deinit(); } update_status(SERVICE_STOP_PENDING); library_deinit(); diff --git a/src/charon-systemd/Makefile.am b/src/charon-systemd/Makefile.am index 1b9ac150f..9942a3682 100644 --- a/src/charon-systemd/Makefile.am +++ b/src/charon-systemd/Makefile.am @@ -7,13 +7,11 @@ charon-systemd.o : $(top_builddir)/config.status charon_systemd_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ - $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \ + $(systemd_CFLAGS) $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \ -DPLUGINS=\""${charon_plugins}\"" charon_systemd_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ - $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB) + $(systemd_LIBS) $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/charon-systemd/Makefile.in b/src/charon-systemd/Makefile.in index d6e1c471c..b4f624d45 100644 --- a/src/charon-systemd/Makefile.in +++ b/src/charon-systemd/Makefile.in @@ -106,10 +106,10 @@ charon_systemd_OBJECTS = $(am_charon_systemd_OBJECTS) am__DEPENDENCIES_1 = charon_systemd_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -387,6 +387,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -405,16 +407,14 @@ charon-systemd.c charon_systemd_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ - $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \ + $(systemd_CFLAGS) $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \ -DPLUGINS=\""${charon_plugins}\"" charon_systemd_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ - $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB) + $(systemd_LIBS) $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB) all: all-am diff --git a/src/charon-systemd/charon-systemd.c b/src/charon-systemd/charon-systemd.c index 4286cde82..5c7bbd779 100644 --- a/src/charon-systemd/charon-systemd.c +++ b/src/charon-systemd/charon-systemd.c @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -325,6 +324,15 @@ static plugin_feature_t features[] = { PLUGIN_PROVIDE(CUSTOM, "systemd-journal"), }; +/** + * Add namespace alias + */ +static void __attribute__ ((constructor))register_namespace() +{ + /* inherit settings from charon */ + library_add_namespace("charon"); +} + /** * Main function, starts the daemon. */ @@ -355,12 +363,6 @@ int main(int argc, char *argv[]) sd_notifyf(0, "STATUS=integrity check of charon-systemd failed"); return SS_RC_INITIALIZATION_FAILED; } - atexit(libhydra_deinit); - if (!libhydra_init()) - { - sd_notifyf(0, "STATUS=libhydra initialization failed"); - return SS_RC_INITIALIZATION_FAILED; - } atexit(libcharon_deinit); if (!libcharon_init()) { diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index d2b81a3ea..ad54eafc0 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -4,15 +4,13 @@ OBJ = $(abs_top_builddir)/src AM_CPPFLAGS = \ -include $(abs_top_builddir)/config.h \ -I$(SRC)/libstrongswan \ - -I$(SRC)/libhydra \ -I$(SRC)/libcharon LIBLD = \ -L$(OBJ)/libstrongswan/.libs \ - -L$(OBJ)/libhydra/.libs \ -L$(OBJ)/libcharon/.libs -LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libhydra/.libs:$(OBJ)/libcharon/.libs -LIBFL = -lstrongswan -lhydra -lcharon +LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libcharon/.libs +LIBFL = -lstrongswan -lcharon DEFS += -DPLUGINS=\""$(PLUGINS)\"" -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/charon-tkm/Makefile.in b/src/charon-tkm/Makefile.in index bff198ab8..81afd4de5 100644 --- a/src/charon-tkm/Makefile.in +++ b/src/charon-tkm/Makefile.in @@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -347,16 +349,14 @@ OBJ = $(abs_top_builddir)/src AM_CPPFLAGS = \ -include $(abs_top_builddir)/config.h \ -I$(SRC)/libstrongswan \ - -I$(SRC)/libhydra \ -I$(SRC)/libcharon LIBLD = \ -L$(OBJ)/libstrongswan/.libs \ - -L$(OBJ)/libhydra/.libs \ -L$(OBJ)/libcharon/.libs -LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libhydra/.libs:$(OBJ)/libcharon/.libs -LIBFL = -lstrongswan -lhydra -lcharon +LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libcharon/.libs +LIBFL = -lstrongswan -lcharon BUILD_OPTS = \ -XOBJ_DIR=$(abs_builddir)/obj \ -cargs $(AM_CPPFLAGS) $(DEFS) \ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 3923c8ae6..13352e55a 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -256,14 +255,6 @@ int main(int argc, char *argv[]) exit(status); } - if (!libhydra_init()) - { - dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name); - libhydra_deinit(); - library_deinit(); - exit(status); - } - if (!libcharon_init()) { dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name); @@ -391,7 +382,6 @@ int main(int argc, char *argv[]) deinit: destroy_dh_mapping(); libcharon_deinit(); - libhydra_deinit(); library_deinit(); tkm_deinit(); return status; diff --git a/src/charon-tkm/src/ees/ees_callbacks.c b/src/charon-tkm/src/ees/ees_callbacks.c index 74c0d3618..f4107d90a 100644 --- a/src/charon-tkm/src/ees/ees_callbacks.c +++ b/src/charon-tkm/src/ees/ees_callbacks.c @@ -14,7 +14,7 @@ * for more details. */ -#include +#include #include #include #include @@ -25,8 +25,7 @@ void charon_esa_acquire(result_type *res, const sp_id_type sp_id) { DBG1(DBG_KNL, "ees: acquire received for reqid %u", sp_id); - hydra->kernel_interface->acquire(hydra->kernel_interface, sp_id, NULL, - NULL); + charon->kernel->acquire(charon->kernel, sp_id, NULL, NULL); *res = TKM_OK; } @@ -47,6 +46,5 @@ void charon_esa_expire(result_type *res, const sp_id_type sp_id, DBG1(DBG_KNL, "ees: expire received for reqid %u, spi %x, dst %H", sp_id, ntohl(spi_rem), dst); - hydra->kernel_interface->expire(hydra->kernel_interface, protocol, - spi_rem, dst, hard != 0); + charon->kernel->expire(charon->kernel, protocol, spi_rem, dst, hard != 0); } diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index d087bee3f..8bba1f9d9 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/src/charon-tkm/tests/tests.c b/src/charon-tkm/tests/tests.c index ac152b690..e3cd2d903 100644 --- a/src/charon-tkm/tests/tests.c +++ b/src/charon-tkm/tests/tests.c @@ -18,7 +18,6 @@ #include #include -#include #include #include "tkm.h" @@ -50,7 +49,6 @@ static bool test_runner_init(bool init) if (init) { - libhydra_init(); libcharon_init(); lib->settings->set_int(lib->settings, "test-runner.filelog.stdout.default", 0); @@ -74,8 +72,6 @@ static bool test_runner_init(bool init) plugin_loader_add_plugindirs(BUILDDIR "/src/libstrongswan/plugins", PLUGINS); - plugin_loader_add_plugindirs(BUILDDIR "/src/libhydra/plugins", - PLUGINS); plugin_loader_add_plugindirs(BUILDDIR "/src/libcharon/plugins", PLUGINS); if (charon->initialize(charon, PLUGINS)) @@ -95,7 +91,6 @@ static bool test_runner_init(bool init) destroy_dh_mapping(); libcharon_deinit(); - libhydra_deinit(); return result; } diff --git a/src/charon/Android.mk b/src/charon/Android.mk index 852d73c10..92a027094 100644 --- a/src/charon/Android.mk +++ b/src/charon/Android.mk @@ -8,7 +8,6 @@ charon.c # build charon ----------------------------------------------------------------- LOCAL_C_INCLUDES += \ - $(strongswan_PATH)/src/libhydra \ $(strongswan_PATH)/src/libcharon \ $(strongswan_PATH)/src/libstrongswan @@ -23,7 +22,7 @@ LOCAL_ARM_MODE := arm LOCAL_PRELINK_MODULE := false -LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libcharon +LOCAL_SHARED_LIBRARIES += libstrongswan libcharon include $(BUILD_EXECUTABLE) diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 6c5b88eb8..c6a6f40f9 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -7,7 +7,6 @@ charon.o : $(top_builddir)/config.status AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -15,7 +14,6 @@ AM_CPPFLAGS = \ charon_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in index e1cc5c202..b4abeff25 100644 --- a/src/charon/Makefile.in +++ b/src/charon/Makefile.in @@ -106,7 +106,6 @@ charon_OBJECTS = $(am_charon_OBJECTS) am__DEPENDENCIES_1 = charon_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) @@ -386,6 +385,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -404,7 +405,6 @@ charon.c AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -412,7 +412,6 @@ AM_CPPFLAGS = \ charon_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/charon/charon.c b/src/charon/charon.c index 4c2a9a477..116ce7e93 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -309,14 +308,6 @@ int main(int argc, char *argv[]) exit(SS_RC_DAEMON_INTEGRITY); } - if (!libhydra_init()) - { - dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon"); - libhydra_deinit(); - library_deinit(); - exit(SS_RC_INITIALIZATION_FAILED); - } - if (!libcharon_init()) { dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon"); @@ -403,7 +394,6 @@ int main(int argc, char *argv[]) { DBG1(DBG_DMN, "integrity tests enabled:"); DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests"); - DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests"); DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests"); DBG1(DBG_DMN, "daemon 'charon': passed file integrity test"); } @@ -457,7 +447,6 @@ int main(int argc, char *argv[]) deinit: libcharon_deinit(); - libhydra_deinit(); library_deinit(); return status; } diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am index b358699d0..9cc5fb6b2 100644 --- a/src/checksum/Makefile.am +++ b/src/checksum/Makefile.am @@ -8,7 +8,6 @@ EXTRA_PROGRAMS = checksum_builder checksum_builder_SOURCES = checksum_builder.c checksum_builder_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(DLLIB) checksum_builder_LDFLAGS = -rpath '$(DESTDIR)$(ipseclibdir)' @@ -17,7 +16,6 @@ CLEANFILES = checksum.c $(EXTRA_PROGRAMS) AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DPLUGINDIR=\"${DESTDIR}${plugindir}\" @@ -35,14 +33,6 @@ if !MONOLITHIC AM_CPPFLAGS += -DS_PLUGINS=\""${s_plugins}\"" endif -if USE_LIBHYDRA - deps += $(top_builddir)/src/libhydra/libhydra.la - libs += $(DESTDIR)$(ipseclibdir)/libhydra.so -if !MONOLITHIC - AM_CPPFLAGS += -DH_PLUGINS=\""${h_plugins}\"" -endif -endif - if USE_LIBIPSEC deps += $(top_builddir)/src/libipsec/libipsec.la libs += $(DESTDIR)$(ipseclibdir)/libipsec.so diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in index 4e4134625..2584beb76 100644 --- a/src/checksum/Makefile.in +++ b/src/checksum/Makefile.in @@ -80,34 +80,31 @@ build_triplet = @build@ host_triplet = @host@ EXTRA_PROGRAMS = checksum_builder$(EXEEXT) @MONOLITHIC_FALSE@am__append_1 = -DS_PLUGINS=\""${s_plugins}\"" -@USE_LIBHYDRA_TRUE@am__append_2 = $(top_builddir)/src/libhydra/libhydra.la -@USE_LIBHYDRA_TRUE@am__append_3 = $(DESTDIR)$(ipseclibdir)/libhydra.so -@MONOLITHIC_FALSE@@USE_LIBHYDRA_TRUE@am__append_4 = -DH_PLUGINS=\""${h_plugins}\"" -@USE_LIBIPSEC_TRUE@am__append_5 = $(top_builddir)/src/libipsec/libipsec.la -@USE_LIBIPSEC_TRUE@am__append_6 = $(DESTDIR)$(ipseclibdir)/libipsec.so -@USE_TLS_TRUE@am__append_7 = $(top_builddir)/src/libtls/libtls.la -@USE_TLS_TRUE@am__append_8 = $(DESTDIR)$(ipseclibdir)/libtls.so -@USE_RADIUS_TRUE@am__append_9 = $(top_builddir)/src/libradius/libradius.la -@USE_RADIUS_TRUE@am__append_10 = $(DESTDIR)$(ipseclibdir)/libradius.so -@USE_LIBPTTLS_TRUE@am__append_11 = $(top_builddir)/src/libpttls/libpttls.la -@USE_LIBPTTLS_TRUE@am__append_12 = $(DESTDIR)$(ipseclibdir)/libpttls.so -@USE_LIBTNCCS_TRUE@am__append_13 = $(top_builddir)/src/libtnccs/libtnccs.la -@USE_LIBTNCCS_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libtnccs.so -@MONOLITHIC_FALSE@@USE_LIBTNCCS_TRUE@am__append_15 = -DT_PLUGINS=\""${t_plugins}\"" -@USE_SIMAKA_TRUE@am__append_16 = $(top_builddir)/src/libsimaka/libsimaka.la -@USE_SIMAKA_TRUE@am__append_17 = $(DESTDIR)$(ipseclibdir)/libsimaka.so -@USE_IMCV_TRUE@am__append_18 = $(top_builddir)/src/libimcv/libimcv.la -@USE_IMCV_TRUE@am__append_19 = $(DESTDIR)$(ipseclibdir)/libimcv.so -@USE_CHARON_TRUE@am__append_20 = $(top_builddir)/src/libcharon/libcharon.la -@USE_CHARON_TRUE@am__append_21 = $(DESTDIR)$(ipseclibdir)/libcharon.so -@USE_CHARON_TRUE@am__append_22 = $(DESTDIR)$(ipsecdir)/charon -@MONOLITHIC_FALSE@@USE_CHARON_TRUE@am__append_23 = -DC_PLUGINS=\""${c_plugins}\"" -@USE_CMD_TRUE@am__append_24 = $(DESTDIR)$(sbindir)/charon-cmd -@USE_SCEPCLIENT_TRUE@am__append_25 = $(DESTDIR)$(ipsecdir)/scepclient -@USE_PKI_TRUE@am__append_26 = $(DESTDIR)$(bindir)/pki -@USE_SWANCTL_TRUE@am__append_27 = $(DESTDIR)$(sbindir)/swanctl -@USE_ATTR_SQL_TRUE@am__append_28 = $(DESTDIR)$(ipsecdir)/pool -@USE_IMV_ATTESTATION_TRUE@am__append_29 = $(DESTDIR)$(ipsecdir)/attest +@USE_LIBIPSEC_TRUE@am__append_2 = $(top_builddir)/src/libipsec/libipsec.la +@USE_LIBIPSEC_TRUE@am__append_3 = $(DESTDIR)$(ipseclibdir)/libipsec.so +@USE_TLS_TRUE@am__append_4 = $(top_builddir)/src/libtls/libtls.la +@USE_TLS_TRUE@am__append_5 = $(DESTDIR)$(ipseclibdir)/libtls.so +@USE_RADIUS_TRUE@am__append_6 = $(top_builddir)/src/libradius/libradius.la +@USE_RADIUS_TRUE@am__append_7 = $(DESTDIR)$(ipseclibdir)/libradius.so +@USE_LIBPTTLS_TRUE@am__append_8 = $(top_builddir)/src/libpttls/libpttls.la +@USE_LIBPTTLS_TRUE@am__append_9 = $(DESTDIR)$(ipseclibdir)/libpttls.so +@USE_LIBTNCCS_TRUE@am__append_10 = $(top_builddir)/src/libtnccs/libtnccs.la +@USE_LIBTNCCS_TRUE@am__append_11 = $(DESTDIR)$(ipseclibdir)/libtnccs.so +@MONOLITHIC_FALSE@@USE_LIBTNCCS_TRUE@am__append_12 = -DT_PLUGINS=\""${t_plugins}\"" +@USE_SIMAKA_TRUE@am__append_13 = $(top_builddir)/src/libsimaka/libsimaka.la +@USE_SIMAKA_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libsimaka.so +@USE_IMCV_TRUE@am__append_15 = $(top_builddir)/src/libimcv/libimcv.la +@USE_IMCV_TRUE@am__append_16 = $(DESTDIR)$(ipseclibdir)/libimcv.so +@USE_CHARON_TRUE@am__append_17 = $(top_builddir)/src/libcharon/libcharon.la +@USE_CHARON_TRUE@am__append_18 = $(DESTDIR)$(ipseclibdir)/libcharon.so +@USE_CHARON_TRUE@am__append_19 = $(DESTDIR)$(ipsecdir)/charon +@MONOLITHIC_FALSE@@USE_CHARON_TRUE@am__append_20 = -DC_PLUGINS=\""${c_plugins}\"" +@USE_CMD_TRUE@am__append_21 = $(DESTDIR)$(sbindir)/charon-cmd +@USE_SCEPCLIENT_TRUE@am__append_22 = $(DESTDIR)$(ipsecdir)/scepclient +@USE_PKI_TRUE@am__append_23 = $(DESTDIR)$(bindir)/pki +@USE_SWANCTL_TRUE@am__append_24 = $(DESTDIR)$(sbindir)/swanctl +@USE_ATTR_SQL_TRUE@am__append_25 = $(DESTDIR)$(ipsecdir)/pool +@USE_IMV_ATTESTATION_TRUE@am__append_26 = $(DESTDIR)$(ipsecdir)/attest subdir = src/checksum DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -173,7 +170,6 @@ checksum_builder_OBJECTS = $(am_checksum_builder_OBJECTS) am__DEPENDENCIES_1 = checksum_builder_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) checksum_builder_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @@ -453,6 +449,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -475,16 +473,15 @@ libchecksum_la_LDFLAGS = -module -avoid-version -rpath '$(ipseclibdir)' checksum_builder_SOURCES = checksum_builder.c checksum_builder_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(DLLIB) checksum_builder_LDFLAGS = -rpath '$(DESTDIR)$(ipseclibdir)' CLEANFILES = checksum.c $(EXTRA_PROGRAMS) AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libcharon \ -DPLUGINDIR=\"${DESTDIR}${plugindir}\" $(am__append_1) \ - $(am__append_4) $(am__append_15) $(am__append_23) + $(am__append_12) $(am__append_20) AM_CFLAGS = \ $(PLUGIN_CFLAGS) @@ -493,16 +490,16 @@ AM_CFLAGS = \ # to the installed libraries. for executables we use the built files directly # as these are not relinked during installation. deps = $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(am__append_2) $(am__append_5) $(am__append_7) \ - $(am__append_9) $(am__append_11) $(am__append_13) \ - $(am__append_16) $(am__append_18) $(am__append_20) + $(am__append_2) $(am__append_4) $(am__append_6) \ + $(am__append_8) $(am__append_10) $(am__append_13) \ + $(am__append_15) $(am__append_17) libs = $(DESTDIR)$(ipseclibdir)/libstrongswan.so $(am__append_3) \ - $(am__append_6) $(am__append_8) $(am__append_10) \ - $(am__append_12) $(am__append_14) $(am__append_17) \ - $(am__append_19) $(am__append_21) -exes = $(am__append_22) $(am__append_24) $(am__append_25) \ - $(am__append_26) $(am__append_27) $(am__append_28) \ - $(am__append_29) + $(am__append_5) $(am__append_7) $(am__append_9) \ + $(am__append_11) $(am__append_14) $(am__append_16) \ + $(am__append_18) +exes = $(am__append_19) $(am__append_21) $(am__append_22) \ + $(am__append_23) $(am__append_24) $(am__append_25) \ + $(am__append_26) all: all-am .SUFFIXES: diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c index cc8185ecd..65399f5bc 100644 --- a/src/checksum/checksum_builder.c +++ b/src/checksum/checksum_builder.c @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -128,9 +127,8 @@ int main(int argc, char* argv[]) { int i; - /* forces link against libhydra/libcharon, imports symbols needed to + /* forces link against libcharon, imports symbols needed to * dlopen plugins */ - hydra = NULL; charon = NULL; /* avoid confusing leak reports in build process */ @@ -159,9 +157,6 @@ int main(int argc, char* argv[]) #ifdef S_PLUGINS build_plugin_checksums(S_PLUGINS); #endif -#ifdef H_PLUGINS - build_plugin_checksums(H_PLUGINS); -#endif #ifdef T_PLUGINS build_plugin_checksums(T_PLUGINS); #endif diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am index eeb26f225..2d4e439da 100644 --- a/src/conftest/Makefile.am +++ b/src/conftest/Makefile.am @@ -2,7 +2,6 @@ ipsec_PROGRAMS = conftest AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DPLUGINS=\""${charon_plugins}\"" @@ -20,7 +19,6 @@ conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \ conftest_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/conftest/Makefile.in b/src/conftest/Makefile.in index 78438d8f5..f5647f9d9 100644 --- a/src/conftest/Makefile.in +++ b/src/conftest/Makefile.in @@ -120,7 +120,6 @@ conftest_OBJECTS = $(am_conftest_OBJECTS) am__DEPENDENCIES_1 = conftest_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) @@ -400,6 +399,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -415,7 +416,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DPLUGINS=\""${charon_plugins}\"" @@ -432,7 +432,6 @@ conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \ conftest_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ $(top_builddir)/src/libcharon/libcharon.la \ -lm $(PTHREADLIB) $(DLLIB) diff --git a/src/conftest/conftest.c b/src/conftest/conftest.c index edfe0ca35..d10f3c7b7 100644 --- a/src/conftest/conftest.c +++ b/src/conftest/conftest.c @@ -356,7 +356,6 @@ static void cleanup() free(conftest->suite_dir); free(conftest); libcharon_deinit(); - libhydra_deinit(); library_deinit(); } @@ -442,16 +441,9 @@ int main(int argc, char *argv[]) library_deinit(); return SS_RC_LIBSTRONGSWAN_INTEGRITY; } - if (!libhydra_init()) - { - libhydra_deinit(); - library_deinit(); - return SS_RC_INITIALIZATION_FAILED; - } if (!libcharon_init()) { libcharon_deinit(); - libhydra_deinit(); library_deinit(); return SS_RC_INITIALIZATION_FAILED; } diff --git a/src/conftest/conftest.h b/src/conftest/conftest.h index 6bbdabd07..2d0320429 100644 --- a/src/conftest/conftest.h +++ b/src/conftest/conftest.h @@ -21,7 +21,6 @@ #define CONFTEST_H_ #include -#include #include #include diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in index 2ecf61194..6525fbcb4 100644 --- a/src/dumm/Makefile.in +++ b/src/dumm/Makefile.in @@ -421,6 +421,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/include/Makefile.in b/src/include/Makefile.in index 5740544ca..9f4becb40 100644 --- a/src/include/Makefile.in +++ b/src/include/Makefile.in @@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in index d4dafcb0c..72022ed56 100644 --- a/src/ipsec/Makefile.in +++ b/src/ipsec/Makefile.in @@ -363,6 +363,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ diff --git a/src/ipsec/_ipsec.8 b/src/ipsec/_ipsec.8 index fa46e79f1..686c1ce80 100644 --- a/src/ipsec/_ipsec.8 +++ b/src/ipsec/_ipsec.8 @@ -1,4 +1,4 @@ -.TH IPSEC 8 "2013-10-29" "5.4.0dr1" "strongSwan" +.TH IPSEC 8 "2013-10-29" "5.4.0rc1" "strongSwan" . .SH NAME . diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in index 89c7ef753..a002614fe 100644 --- a/src/ipsec/_ipsec.in +++ b/src/ipsec/_ipsec.in @@ -259,10 +259,15 @@ stop) loop=110 while [ $loop -gt 0 ] ; do kill -0 $spid 2>/dev/null || break - sleep 0.1 + sleep 0.1 2>/dev/null + if [ $? -ne 0 ] + then + sleep 1 + loop=$(($loop - 9)) + fi loop=$(($loop - 1)) done - if [ $loop -eq 0 ] + if [ $loop -le 0 ] then kill -KILL $spid 2>/dev/null rm -f $IPSEC_STARTER_PID diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 10085794b..55e6bc58b 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -47,7 +47,10 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \ encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \ encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \ -kernel/kernel_handler.c kernel/kernel_handler.h \ +kernel/kernel_interface.c kernel/kernel_interface.h \ +kernel/kernel_ipsec.c kernel/kernel_ipsec.h \ +kernel/kernel_net.c kernel/kernel_net.h \ +kernel/kernel_listener.h kernel/kernel_handler.c kernel/kernel_handler.h \ network/receiver.c network/receiver.h network/sender.c network/sender.h \ network/socket.c network/socket.h \ network/socket_manager.c network/socket_manager.h \ @@ -56,6 +59,7 @@ processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \ processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \ processing/jobs/process_message_job.c processing/jobs/process_message_job.h \ +processing/jobs/redirect_job.c processing/jobs/redirect_job.h \ processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \ processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \ processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \ @@ -81,6 +85,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ +sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \ sa/task.c sa/task.h libcharon_la_SOURCES += \ @@ -104,8 +109,10 @@ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ +sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \ sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ -sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h +sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \ +sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h libcharon_la_SOURCES += \ sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \ @@ -149,6 +156,8 @@ endif LOCAL_SRC_FILES += $(call add_plugin, attr) +LOCAL_SRC_FILES += $(call add_plugin, p-cscf) + LOCAL_SRC_FILES += $(call add_plugin, eap-aka) LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2) @@ -216,6 +225,10 @@ endif LOCAL_SRC_FILES += $(call add_plugin, load-tester) +LOCAL_SRC_FILES += $(call add_plugin, kernel-pfkey) + +LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink) + LOCAL_SRC_FILES += $(call add_plugin, socket-default) LOCAL_SRC_FILES += $(call add_plugin, socket-dynamic) @@ -228,7 +241,6 @@ endif # build libcharon -------------------------------------------------------------- LOCAL_C_INCLUDES += \ - $(strongswan_PATH)/src/libhydra \ $(strongswan_PATH)/src/libstrongswan LOCAL_CFLAGS := $(strongswan_CFLAGS) @@ -241,6 +253,6 @@ LOCAL_ARM_MODE := arm LOCAL_PRELINK_MODULE := false -LOCAL_SHARED_LIBRARIES += libstrongswan libhydra +LOCAL_SHARED_LIBRARIES += libstrongswan include $(BUILD_SHARED_LIBRARY) diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index cd81a5eee..9f0707813 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -8,6 +8,7 @@ attributes/mem_pool.c attributes/mem_pool.h \ bus/bus.c bus/bus.h \ bus/listeners/listener.h \ bus/listeners/logger.h \ +bus/listeners/custom_logger.h \ bus/listeners/file_logger.c bus/listeners/file_logger.h \ config/backend_manager.c config/backend_manager.h config/backend.h \ config/child_cfg.c config/child_cfg.h \ @@ -45,7 +46,10 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \ encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \ encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \ -kernel/kernel_handler.c kernel/kernel_handler.h \ +kernel/kernel_interface.c kernel/kernel_interface.h \ +kernel/kernel_ipsec.c kernel/kernel_ipsec.h \ +kernel/kernel_net.c kernel/kernel_net.h \ +kernel/kernel_listener.h kernel/kernel_handler.c kernel/kernel_handler.h \ network/receiver.c network/receiver.h network/sender.c network/sender.h \ network/socket.c network/socket.h \ network/socket_manager.c network/socket_manager.h \ @@ -54,6 +58,7 @@ processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \ processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \ processing/jobs/process_message_job.c processing/jobs/process_message_job.h \ +processing/jobs/redirect_job.c processing/jobs/redirect_job.h \ processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \ processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \ processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \ @@ -79,6 +84,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ +sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \ sa/task.c sa/task.h if USE_IKEV2 @@ -103,8 +109,10 @@ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ +sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \ sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ -sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h +sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \ +sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h endif if USE_IKEV1 @@ -142,7 +150,6 @@ daemon.lo : $(top_builddir)/config.status AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" @@ -152,7 +159,6 @@ AM_LDFLAGS = \ libcharon_la_LIBADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la \ -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) if USE_WINDOWS @@ -483,6 +489,13 @@ if MONOLITHIC endif endif +if USE_P_CSCF + SUBDIRS += plugins/p_cscf +if MONOLITHIC + libcharon_la_LIBADD += plugins/p_cscf/libstrongswan-p-cscf.la +endif +endif + if USE_ANDROID_DNS SUBDIRS += plugins/android_dns if MONOLITHIC @@ -511,6 +524,27 @@ if MONOLITHIC endif endif +if USE_KERNEL_PFKEY + SUBDIRS += plugins/kernel_pfkey +if MONOLITHIC + libcharon_la_LIBADD += plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la +endif +endif + +if USE_KERNEL_PFROUTE + SUBDIRS += plugins/kernel_pfroute +if MONOLITHIC + libcharon_la_LIBADD += plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la +endif +endif + +if USE_KERNEL_NETLINK + SUBDIRS += plugins/kernel_netlink +if MONOLITHIC + libcharon_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la +endif +endif + if USE_KERNEL_LIBIPSEC SUBDIRS += plugins/kernel_libipsec if MONOLITHIC diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in index 3d425e0b4..2ccae216e 100644 --- a/src/libcharon/Makefile.in +++ b/src/libcharon/Makefile.in @@ -99,8 +99,10 @@ host_triplet = @host@ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ +@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ -@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h +@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \ +@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h @USE_IKEV1_TRUE@am__append_2 = \ @USE_IKEV1_TRUE@sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \ @@ -221,58 +223,66 @@ host_triplet = @host@ @MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_85 = plugins/dhcp/libstrongswan-dhcp.la @USE_OSX_ATTR_TRUE@am__append_86 = plugins/osx_attr @MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_87 = plugins/osx_attr/libstrongswan-osx-attr.la -@USE_ANDROID_DNS_TRUE@am__append_88 = plugins/android_dns -@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_89 = plugins/android_dns/libstrongswan-android-dns.la -@USE_ANDROID_LOG_TRUE@am__append_90 = plugins/android_log -@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_91 = plugins/android_log/libstrongswan-android-log.la -@USE_MAEMO_TRUE@am__append_92 = plugins/maemo -@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_93 = plugins/maemo/libstrongswan-maemo.la -@USE_HA_TRUE@am__append_94 = plugins/ha -@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_95 = plugins/ha/libstrongswan-ha.la -@USE_KERNEL_LIBIPSEC_TRUE@am__append_96 = plugins/kernel_libipsec -@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_97 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la -@USE_KERNEL_WFP_TRUE@am__append_98 = plugins/kernel_wfp -@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_99 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la -@USE_KERNEL_IPH_TRUE@am__append_100 = plugins/kernel_iph -@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_101 = plugins/kernel_iph/libstrongswan-kernel-iph.la -@USE_WHITELIST_TRUE@am__append_102 = plugins/whitelist -@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_103 = plugins/whitelist/libstrongswan-whitelist.la -@USE_LOOKIP_TRUE@am__append_104 = plugins/lookip -@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_105 = plugins/lookip/libstrongswan-lookip.la -@USE_ERROR_NOTIFY_TRUE@am__append_106 = plugins/error_notify -@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_107 = plugins/error_notify/libstrongswan-error-notify.la -@USE_CERTEXPIRE_TRUE@am__append_108 = plugins/certexpire -@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_109 = plugins/certexpire/libstrongswan-certexpire.la -@USE_SYSTIME_FIX_TRUE@am__append_110 = plugins/systime_fix -@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_111 = plugins/systime_fix/libstrongswan-systime-fix.la -@USE_LED_TRUE@am__append_112 = plugins/led -@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_113 = plugins/led/libstrongswan-led.la -@USE_DUPLICHECK_TRUE@am__append_114 = plugins/duplicheck -@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_115 = plugins/duplicheck/libstrongswan-duplicheck.la -@USE_COUPLING_TRUE@am__append_116 = plugins/coupling -@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_117 = plugins/coupling/libstrongswan-coupling.la -@USE_RADATTR_TRUE@am__append_118 = plugins/radattr -@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_119 = plugins/radattr/libstrongswan-radattr.la -@USE_UCI_TRUE@am__append_120 = plugins/uci -@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_121 = plugins/uci/libstrongswan-uci.la -@USE_ADDRBLOCK_TRUE@am__append_122 = plugins/addrblock -@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_123 = plugins/addrblock/libstrongswan-addrblock.la -@USE_UNITY_TRUE@am__append_124 = plugins/unity -@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_125 = plugins/unity/libstrongswan-unity.la -@USE_XAUTH_GENERIC_TRUE@am__append_126 = plugins/xauth_generic -@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_127 = plugins/xauth_generic/libstrongswan-xauth-generic.la -@USE_XAUTH_EAP_TRUE@am__append_128 = plugins/xauth_eap -@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_129 = plugins/xauth_eap/libstrongswan-xauth-eap.la -@USE_XAUTH_PAM_TRUE@am__append_130 = plugins/xauth_pam -@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_131 = plugins/xauth_pam/libstrongswan-xauth-pam.la -@USE_XAUTH_NOAUTH_TRUE@am__append_132 = plugins/xauth_noauth -@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_133 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la -@USE_RESOLVE_TRUE@am__append_134 = plugins/resolve -@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_135 = plugins/resolve/libstrongswan-resolve.la -@USE_ATTR_TRUE@am__append_136 = plugins/attr -@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_137 = plugins/attr/libstrongswan-attr.la -@USE_ATTR_SQL_TRUE@am__append_138 = plugins/attr_sql -@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_139 = plugins/attr_sql/libstrongswan-attr-sql.la +@USE_P_CSCF_TRUE@am__append_88 = plugins/p_cscf +@MONOLITHIC_TRUE@@USE_P_CSCF_TRUE@am__append_89 = plugins/p_cscf/libstrongswan-p-cscf.la +@USE_ANDROID_DNS_TRUE@am__append_90 = plugins/android_dns +@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_91 = plugins/android_dns/libstrongswan-android-dns.la +@USE_ANDROID_LOG_TRUE@am__append_92 = plugins/android_log +@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_93 = plugins/android_log/libstrongswan-android-log.la +@USE_MAEMO_TRUE@am__append_94 = plugins/maemo +@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_95 = plugins/maemo/libstrongswan-maemo.la +@USE_HA_TRUE@am__append_96 = plugins/ha +@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_97 = plugins/ha/libstrongswan-ha.la +@USE_KERNEL_PFKEY_TRUE@am__append_98 = plugins/kernel_pfkey +@MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE@am__append_99 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la +@USE_KERNEL_PFROUTE_TRUE@am__append_100 = plugins/kernel_pfroute +@MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE@am__append_101 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la +@USE_KERNEL_NETLINK_TRUE@am__append_102 = plugins/kernel_netlink +@MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE@am__append_103 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la +@USE_KERNEL_LIBIPSEC_TRUE@am__append_104 = plugins/kernel_libipsec +@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_105 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la +@USE_KERNEL_WFP_TRUE@am__append_106 = plugins/kernel_wfp +@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_107 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la +@USE_KERNEL_IPH_TRUE@am__append_108 = plugins/kernel_iph +@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_109 = plugins/kernel_iph/libstrongswan-kernel-iph.la +@USE_WHITELIST_TRUE@am__append_110 = plugins/whitelist +@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_111 = plugins/whitelist/libstrongswan-whitelist.la +@USE_LOOKIP_TRUE@am__append_112 = plugins/lookip +@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_113 = plugins/lookip/libstrongswan-lookip.la +@USE_ERROR_NOTIFY_TRUE@am__append_114 = plugins/error_notify +@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_115 = plugins/error_notify/libstrongswan-error-notify.la +@USE_CERTEXPIRE_TRUE@am__append_116 = plugins/certexpire +@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_117 = plugins/certexpire/libstrongswan-certexpire.la +@USE_SYSTIME_FIX_TRUE@am__append_118 = plugins/systime_fix +@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_119 = plugins/systime_fix/libstrongswan-systime-fix.la +@USE_LED_TRUE@am__append_120 = plugins/led +@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_121 = plugins/led/libstrongswan-led.la +@USE_DUPLICHECK_TRUE@am__append_122 = plugins/duplicheck +@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_123 = plugins/duplicheck/libstrongswan-duplicheck.la +@USE_COUPLING_TRUE@am__append_124 = plugins/coupling +@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_125 = plugins/coupling/libstrongswan-coupling.la +@USE_RADATTR_TRUE@am__append_126 = plugins/radattr +@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_127 = plugins/radattr/libstrongswan-radattr.la +@USE_UCI_TRUE@am__append_128 = plugins/uci +@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_129 = plugins/uci/libstrongswan-uci.la +@USE_ADDRBLOCK_TRUE@am__append_130 = plugins/addrblock +@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_131 = plugins/addrblock/libstrongswan-addrblock.la +@USE_UNITY_TRUE@am__append_132 = plugins/unity +@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_133 = plugins/unity/libstrongswan-unity.la +@USE_XAUTH_GENERIC_TRUE@am__append_134 = plugins/xauth_generic +@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_135 = plugins/xauth_generic/libstrongswan-xauth-generic.la +@USE_XAUTH_EAP_TRUE@am__append_136 = plugins/xauth_eap +@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_137 = plugins/xauth_eap/libstrongswan-xauth-eap.la +@USE_XAUTH_PAM_TRUE@am__append_138 = plugins/xauth_pam +@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_139 = plugins/xauth_pam/libstrongswan-xauth-pam.la +@USE_XAUTH_NOAUTH_TRUE@am__append_140 = plugins/xauth_noauth +@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_141 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la +@USE_RESOLVE_TRUE@am__append_142 = plugins/resolve +@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_143 = plugins/resolve/libstrongswan-resolve.la +@USE_ATTR_TRUE@am__append_144 = plugins/attr +@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_145 = plugins/attr/libstrongswan-attr.la +@USE_ATTR_SQL_TRUE@am__append_146 = plugins/attr_sql +@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_147 = plugins/attr_sql/libstrongswan-attr-sql.la subdir = src/libcharon DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -325,47 +335,47 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES) am__DEPENDENCIES_1 = libcharon_la_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__append_7) $(am__append_9) \ - $(am__append_11) $(am__append_13) $(am__append_15) \ - $(am__append_17) $(am__append_19) $(am__append_21) \ - $(am__append_23) $(am__append_25) $(am__append_27) \ - $(am__append_29) $(am__append_31) $(am__append_33) \ - $(am__append_35) $(am__append_37) $(am__append_39) \ - $(am__append_41) $(am__append_43) $(am__append_45) \ - $(am__append_47) $(am__append_49) $(am__append_51) \ - $(am__append_53) $(am__append_54) $(am__append_56) \ - $(am__append_58) $(am__append_60) $(am__append_62) \ - $(am__append_64) $(am__append_66) $(am__append_68) \ - $(am__append_70) $(am__append_72) $(am__append_73) \ - $(am__append_74) $(am__append_76) $(am__append_78) \ - $(am__append_79) $(am__append_81) $(am__append_83) \ - $(am__append_85) $(am__append_87) $(am__append_89) \ - $(am__append_91) $(am__append_93) $(am__append_95) \ - $(am__append_97) $(am__append_99) $(am__append_101) \ - $(am__append_103) $(am__append_105) $(am__append_107) \ - $(am__append_109) $(am__append_111) $(am__append_113) \ - $(am__append_115) $(am__append_117) $(am__append_119) \ - $(am__append_121) $(am__append_123) $(am__append_125) \ - $(am__append_127) $(am__append_129) $(am__append_131) \ - $(am__append_133) $(am__append_135) $(am__append_137) \ - $(am__append_139) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(am__append_7) \ + $(am__append_9) $(am__append_11) $(am__append_13) \ + $(am__append_15) $(am__append_17) $(am__append_19) \ + $(am__append_21) $(am__append_23) $(am__append_25) \ + $(am__append_27) $(am__append_29) $(am__append_31) \ + $(am__append_33) $(am__append_35) $(am__append_37) \ + $(am__append_39) $(am__append_41) $(am__append_43) \ + $(am__append_45) $(am__append_47) $(am__append_49) \ + $(am__append_51) $(am__append_53) $(am__append_54) \ + $(am__append_56) $(am__append_58) $(am__append_60) \ + $(am__append_62) $(am__append_64) $(am__append_66) \ + $(am__append_68) $(am__append_70) $(am__append_72) \ + $(am__append_73) $(am__append_74) $(am__append_76) \ + $(am__append_78) $(am__append_79) $(am__append_81) \ + $(am__append_83) $(am__append_85) $(am__append_87) \ + $(am__append_89) $(am__append_91) $(am__append_93) \ + $(am__append_95) $(am__append_97) $(am__append_99) \ + $(am__append_101) $(am__append_103) $(am__append_105) \ + $(am__append_107) $(am__append_109) $(am__append_111) \ + $(am__append_113) $(am__append_115) $(am__append_117) \ + $(am__append_119) $(am__append_121) $(am__append_123) \ + $(am__append_125) $(am__append_127) $(am__append_129) \ + $(am__append_131) $(am__append_133) $(am__append_135) \ + $(am__append_137) $(am__append_139) $(am__append_141) \ + $(am__append_143) $(am__append_145) $(am__append_147) am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ attributes/attributes.h attributes/attribute_provider.h \ attributes/attribute_handler.h attributes/attribute_manager.c \ attributes/attribute_manager.h attributes/mem_pool.c \ attributes/mem_pool.h bus/bus.c bus/bus.h \ bus/listeners/listener.h bus/listeners/logger.h \ - bus/listeners/file_logger.c bus/listeners/file_logger.h \ - config/backend_manager.c config/backend_manager.h \ - config/backend.h config/child_cfg.c config/child_cfg.h \ - config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \ - config/peer_cfg.h config/proposal.c config/proposal.h \ - control/controller.c control/controller.h daemon.c daemon.h \ - encoding/generator.c encoding/generator.h encoding/message.c \ - encoding/message.h encoding/parser.c encoding/parser.h \ - encoding/payloads/auth_payload.c \ + bus/listeners/custom_logger.h bus/listeners/file_logger.c \ + bus/listeners/file_logger.h config/backend_manager.c \ + config/backend_manager.h config/backend.h config/child_cfg.c \ + config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \ + config/peer_cfg.c config/peer_cfg.h config/proposal.c \ + config/proposal.h control/controller.c control/controller.h \ + daemon.c daemon.h encoding/generator.c encoding/generator.h \ + encoding/message.c encoding/message.h encoding/parser.c \ + encoding/parser.h encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ encoding/payloads/cert_payload.h \ @@ -407,7 +417,10 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ encoding/payloads/hash_payload.c \ encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c \ - encoding/payloads/fragment_payload.h kernel/kernel_handler.c \ + encoding/payloads/fragment_payload.h kernel/kernel_interface.c \ + kernel/kernel_interface.h kernel/kernel_ipsec.c \ + kernel/kernel_ipsec.h kernel/kernel_net.c kernel/kernel_net.h \ + kernel/kernel_listener.h kernel/kernel_handler.c \ kernel/kernel_handler.h network/receiver.c network/receiver.h \ network/sender.c network/sender.h network/socket.c \ network/socket.h network/socket_manager.c \ @@ -420,6 +433,7 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \ processing/jobs/process_message_job.c \ processing/jobs/process_message_job.h \ + processing/jobs/redirect_job.c processing/jobs/redirect_job.h \ processing/jobs/rekey_child_sa_job.c \ processing/jobs/rekey_child_sa_job.h \ processing/jobs/rekey_ike_sa_job.c \ @@ -449,7 +463,8 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ sa/ike_sa_manager.h sa/child_sa_manager.c \ sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \ - sa/trap_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \ + sa/trap_manager.h sa/redirect_provider.h sa/redirect_manager.c \ + sa/redirect_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \ sa/ikev2/keymat_v2.h sa/ikev2/task_manager_v2.c \ sa/ikev2/task_manager_v2.h \ sa/ikev2/authenticators/eap_authenticator.c \ @@ -474,9 +489,12 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ sa/ikev2/tasks/ike_reauth_complete.c \ sa/ikev2/tasks/ike_reauth_complete.h \ + sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \ sa/ikev2/tasks/ike_auth_lifetime.c \ sa/ikev2/tasks/ike_auth_lifetime.h sa/ikev2/tasks/ike_vendor.c \ - sa/ikev2/tasks/ike_vendor.h sa/ikev1/keymat_v1.c \ + sa/ikev2/tasks/ike_vendor.h \ + sa/ikev2/tasks/ike_verify_peer_cert.c \ + sa/ikev2/tasks/ike_verify_peer_cert.h sa/ikev1/keymat_v1.c \ sa/ikev1/keymat_v1.h sa/ikev1/task_manager_v1.c \ sa/ikev1/task_manager_v1.h \ sa/ikev1/authenticators/psk_v1_authenticator.c \ @@ -535,8 +553,10 @@ am__dirstamp = $(am__leading_dot)dirstamp @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_rekey.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_reauth.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_reauth_complete.lo \ +@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_redirect.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_auth_lifetime.lo \ -@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_vendor.lo +@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_vendor.lo \ +@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_verify_peer_cert.lo @USE_IKEV1_TRUE@am__objects_2 = sa/ikev1/keymat_v1.lo \ @USE_IKEV1_TRUE@ sa/ikev1/task_manager_v1.lo \ @USE_IKEV1_TRUE@ sa/ikev1/authenticators/psk_v1_authenticator.lo \ @@ -595,13 +615,16 @@ am_libcharon_la_OBJECTS = attributes/attributes.lo \ encoding/payloads/unknown_payload.lo \ encoding/payloads/vendor_id_payload.lo \ encoding/payloads/hash_payload.lo \ - encoding/payloads/fragment_payload.lo kernel/kernel_handler.lo \ + encoding/payloads/fragment_payload.lo \ + kernel/kernel_interface.lo kernel/kernel_ipsec.lo \ + kernel/kernel_net.lo kernel/kernel_handler.lo \ network/receiver.lo network/sender.lo network/socket.lo \ network/socket_manager.lo processing/jobs/acquire_job.lo \ processing/jobs/delete_child_sa_job.lo \ processing/jobs/delete_ike_sa_job.lo \ processing/jobs/migrate_job.lo \ processing/jobs/process_message_job.lo \ + processing/jobs/redirect_job.lo \ processing/jobs/rekey_child_sa_job.lo \ processing/jobs/rekey_ike_sa_job.lo \ processing/jobs/retransmit_job.lo \ @@ -616,8 +639,9 @@ am_libcharon_la_OBJECTS = attributes/attributes.lo \ sa/xauth/xauth_manager.lo sa/authenticator.lo sa/child_sa.lo \ sa/ike_sa.lo sa/ike_sa_id.lo sa/keymat.lo sa/ike_sa_manager.lo \ sa/child_sa_manager.lo sa/task_manager.lo sa/shunt_manager.lo \ - sa/trap_manager.lo sa/task.lo $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + sa/trap_manager.lo sa/redirect_manager.lo sa/task.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -712,12 +736,14 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \ plugins/eap_tls plugins/eap_ttls plugins/eap_peap \ plugins/eap_tnc plugins/tnc_ifmap plugins/tnc_pdp \ plugins/medsrv plugins/medcli plugins/dhcp plugins/osx_attr \ - plugins/android_dns plugins/android_log plugins/maemo \ - plugins/ha plugins/kernel_libipsec plugins/kernel_wfp \ - plugins/kernel_iph plugins/whitelist plugins/lookip \ - plugins/error_notify plugins/certexpire plugins/systime_fix \ - plugins/led plugins/duplicheck plugins/coupling \ - plugins/radattr plugins/uci plugins/addrblock plugins/unity \ + plugins/p_cscf plugins/android_dns plugins/android_log \ + plugins/maemo plugins/ha plugins/kernel_pfkey \ + plugins/kernel_pfroute plugins/kernel_netlink \ + plugins/kernel_libipsec plugins/kernel_wfp plugins/kernel_iph \ + plugins/whitelist plugins/lookip plugins/error_notify \ + plugins/certexpire plugins/systime_fix plugins/led \ + plugins/duplicheck plugins/coupling plugins/radattr \ + plugins/uci plugins/addrblock plugins/unity \ plugins/xauth_generic plugins/xauth_eap plugins/xauth_pam \ plugins/xauth_noauth plugins/resolve plugins/attr \ plugins/attr_sql tests @@ -959,6 +985,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -978,15 +1006,15 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \ attributes/attribute_manager.c attributes/attribute_manager.h \ attributes/mem_pool.c attributes/mem_pool.h bus/bus.c \ bus/bus.h bus/listeners/listener.h bus/listeners/logger.h \ - bus/listeners/file_logger.c bus/listeners/file_logger.h \ - config/backend_manager.c config/backend_manager.h \ - config/backend.h config/child_cfg.c config/child_cfg.h \ - config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \ - config/peer_cfg.h config/proposal.c config/proposal.h \ - control/controller.c control/controller.h daemon.c daemon.h \ - encoding/generator.c encoding/generator.h encoding/message.c \ - encoding/message.h encoding/parser.c encoding/parser.h \ - encoding/payloads/auth_payload.c \ + bus/listeners/custom_logger.h bus/listeners/file_logger.c \ + bus/listeners/file_logger.h config/backend_manager.c \ + config/backend_manager.h config/backend.h config/child_cfg.c \ + config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \ + config/peer_cfg.c config/peer_cfg.h config/proposal.c \ + config/proposal.h control/controller.c control/controller.h \ + daemon.c daemon.h encoding/generator.c encoding/generator.h \ + encoding/message.c encoding/message.h encoding/parser.c \ + encoding/parser.h encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ encoding/payloads/cert_payload.h \ @@ -1028,7 +1056,10 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \ encoding/payloads/hash_payload.c \ encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c \ - encoding/payloads/fragment_payload.h kernel/kernel_handler.c \ + encoding/payloads/fragment_payload.h kernel/kernel_interface.c \ + kernel/kernel_interface.h kernel/kernel_ipsec.c \ + kernel/kernel_ipsec.h kernel/kernel_net.c kernel/kernel_net.h \ + kernel/kernel_listener.h kernel/kernel_handler.c \ kernel/kernel_handler.h network/receiver.c network/receiver.h \ network/sender.c network/sender.h network/socket.c \ network/socket.h network/socket_manager.c \ @@ -1041,6 +1072,7 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \ processing/jobs/process_message_job.c \ processing/jobs/process_message_job.h \ + processing/jobs/redirect_job.c processing/jobs/redirect_job.h \ processing/jobs/rekey_child_sa_job.c \ processing/jobs/rekey_child_sa_job.h \ processing/jobs/rekey_ike_sa_job.c \ @@ -1070,12 +1102,12 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \ sa/ike_sa_manager.h sa/child_sa_manager.c \ sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \ - sa/trap_manager.h sa/task.c sa/task.h $(am__append_1) \ + sa/trap_manager.h sa/redirect_provider.h sa/redirect_manager.c \ + sa/redirect_manager.h sa/task.c sa/task.h $(am__append_1) \ $(am__append_2) $(am__append_3) $(am__append_5) AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" @@ -1084,32 +1116,33 @@ AM_LDFLAGS = \ -no-undefined libcharon_la_LIBADD = \ - $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(top_builddir)/src/libhydra/libhydra.la -lm $(PTHREADLIB) \ - $(DLLIB) $(SOCKLIB) $(am__append_4) $(am__append_7) \ - $(am__append_9) $(am__append_11) $(am__append_13) \ - $(am__append_15) $(am__append_17) $(am__append_19) \ - $(am__append_21) $(am__append_23) $(am__append_25) \ - $(am__append_27) $(am__append_29) $(am__append_31) \ - $(am__append_33) $(am__append_35) $(am__append_37) \ - $(am__append_39) $(am__append_41) $(am__append_43) \ - $(am__append_45) $(am__append_47) $(am__append_49) \ - $(am__append_51) $(am__append_53) $(am__append_54) \ - $(am__append_56) $(am__append_58) $(am__append_60) \ - $(am__append_62) $(am__append_64) $(am__append_66) \ - $(am__append_68) $(am__append_70) $(am__append_72) \ - $(am__append_73) $(am__append_74) $(am__append_76) \ - $(am__append_78) $(am__append_79) $(am__append_81) \ - $(am__append_83) $(am__append_85) $(am__append_87) \ - $(am__append_89) $(am__append_91) $(am__append_93) \ - $(am__append_95) $(am__append_97) $(am__append_99) \ - $(am__append_101) $(am__append_103) $(am__append_105) \ - $(am__append_107) $(am__append_109) $(am__append_111) \ - $(am__append_113) $(am__append_115) $(am__append_117) \ - $(am__append_119) $(am__append_121) $(am__append_123) \ - $(am__append_125) $(am__append_127) $(am__append_129) \ - $(am__append_131) $(am__append_133) $(am__append_135) \ - $(am__append_137) $(am__append_139) + $(top_builddir)/src/libstrongswan/libstrongswan.la -lm \ + $(PTHREADLIB) $(DLLIB) $(SOCKLIB) $(am__append_4) \ + $(am__append_7) $(am__append_9) $(am__append_11) \ + $(am__append_13) $(am__append_15) $(am__append_17) \ + $(am__append_19) $(am__append_21) $(am__append_23) \ + $(am__append_25) $(am__append_27) $(am__append_29) \ + $(am__append_31) $(am__append_33) $(am__append_35) \ + $(am__append_37) $(am__append_39) $(am__append_41) \ + $(am__append_43) $(am__append_45) $(am__append_47) \ + $(am__append_49) $(am__append_51) $(am__append_53) \ + $(am__append_54) $(am__append_56) $(am__append_58) \ + $(am__append_60) $(am__append_62) $(am__append_64) \ + $(am__append_66) $(am__append_68) $(am__append_70) \ + $(am__append_72) $(am__append_73) $(am__append_74) \ + $(am__append_76) $(am__append_78) $(am__append_79) \ + $(am__append_81) $(am__append_83) $(am__append_85) \ + $(am__append_87) $(am__append_89) $(am__append_91) \ + $(am__append_93) $(am__append_95) $(am__append_97) \ + $(am__append_99) $(am__append_101) $(am__append_103) \ + $(am__append_105) $(am__append_107) $(am__append_109) \ + $(am__append_111) $(am__append_113) $(am__append_115) \ + $(am__append_117) $(am__append_119) $(am__append_121) \ + $(am__append_123) $(am__append_125) $(am__append_127) \ + $(am__append_129) $(am__append_131) $(am__append_133) \ + $(am__append_135) $(am__append_137) $(am__append_139) \ + $(am__append_141) $(am__append_143) $(am__append_145) \ + $(am__append_147) EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \ @MONOLITHIC_FALSE@ $(am__append_10) $(am__append_12) \ @@ -1143,7 +1176,9 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_126) $(am__append_128) \ @MONOLITHIC_FALSE@ $(am__append_130) $(am__append_132) \ @MONOLITHIC_FALSE@ $(am__append_134) $(am__append_136) \ -@MONOLITHIC_FALSE@ $(am__append_138) tests +@MONOLITHIC_FALSE@ $(am__append_138) $(am__append_140) \ +@MONOLITHIC_FALSE@ $(am__append_142) $(am__append_144) \ +@MONOLITHIC_FALSE@ $(am__append_146) tests # build optional plugins ######################## @@ -1179,7 +1214,9 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_126) $(am__append_128) \ @MONOLITHIC_TRUE@ $(am__append_130) $(am__append_132) \ @MONOLITHIC_TRUE@ $(am__append_134) $(am__append_136) \ -@MONOLITHIC_TRUE@ $(am__append_138) . tests +@MONOLITHIC_TRUE@ $(am__append_138) $(am__append_140) \ +@MONOLITHIC_TRUE@ $(am__append_142) $(am__append_144) \ +@MONOLITHIC_TRUE@ $(am__append_146) . tests all: all-recursive .SUFFIXES: @@ -1386,6 +1423,12 @@ kernel/$(am__dirstamp): kernel/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) kernel/$(DEPDIR) @: > kernel/$(DEPDIR)/$(am__dirstamp) +kernel/kernel_interface.lo: kernel/$(am__dirstamp) \ + kernel/$(DEPDIR)/$(am__dirstamp) +kernel/kernel_ipsec.lo: kernel/$(am__dirstamp) \ + kernel/$(DEPDIR)/$(am__dirstamp) +kernel/kernel_net.lo: kernel/$(am__dirstamp) \ + kernel/$(DEPDIR)/$(am__dirstamp) kernel/kernel_handler.lo: kernel/$(am__dirstamp) \ kernel/$(DEPDIR)/$(am__dirstamp) network/$(am__dirstamp): @@ -1420,6 +1463,8 @@ processing/jobs/migrate_job.lo: processing/jobs/$(am__dirstamp) \ processing/jobs/process_message_job.lo: \ processing/jobs/$(am__dirstamp) \ processing/jobs/$(DEPDIR)/$(am__dirstamp) +processing/jobs/redirect_job.lo: processing/jobs/$(am__dirstamp) \ + processing/jobs/$(DEPDIR)/$(am__dirstamp) processing/jobs/rekey_child_sa_job.lo: \ processing/jobs/$(am__dirstamp) \ processing/jobs/$(DEPDIR)/$(am__dirstamp) @@ -1483,6 +1528,8 @@ sa/child_sa_manager.lo: sa/$(am__dirstamp) \ sa/task_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/shunt_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/trap_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) +sa/redirect_manager.lo: sa/$(am__dirstamp) \ + sa/$(DEPDIR)/$(am__dirstamp) sa/task.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/ikev2/$(am__dirstamp): @$(MKDIR_P) sa/ikev2 @@ -1545,10 +1592,15 @@ sa/ikev2/tasks/ike_reauth.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_reauth_complete.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) +sa/ikev2/tasks/ike_redirect.lo: sa/ikev2/tasks/$(am__dirstamp) \ + sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_auth_lifetime.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_vendor.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) +sa/ikev2/tasks/ike_verify_peer_cert.lo: \ + sa/ikev2/tasks/$(am__dirstamp) \ + sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev1/$(am__dirstamp): @$(MKDIR_P) sa/ikev1 @: > sa/ikev1/$(am__dirstamp) @@ -1720,6 +1772,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/unknown_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/vendor_id_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@kernel/$(DEPDIR)/kernel_handler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@kernel/$(DEPDIR)/kernel_interface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@kernel/$(DEPDIR)/kernel_ipsec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@kernel/$(DEPDIR)/kernel_net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@network/$(DEPDIR)/receiver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@network/$(DEPDIR)/sender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@network/$(DEPDIR)/socket.Plo@am__quote@ @@ -1735,6 +1790,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/mediation_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/migrate_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/process_message_job.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/redirect_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/rekey_child_sa_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/rekey_ike_sa_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/retransmit_job.Plo@am__quote@ @@ -1751,6 +1807,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/ike_sa_id.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/ike_sa_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/keymat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/redirect_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/shunt_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/task.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/task_manager.Plo@am__quote@ @@ -1799,8 +1856,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_natd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_reauth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_reauth_complete.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_redirect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_rekey.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_vendor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_verify_peer_cert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/xauth/$(DEPDIR)/xauth_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/xauth/$(DEPDIR)/xauth_method.Plo@am__quote@ diff --git a/src/libcharon/attributes/attributes.c b/src/libcharon/attributes/attributes.c index 9fabcf4e4..0f28d55fa 100644 --- a/src/libcharon/attributes/attributes.c +++ b/src/libcharon/attributes/attributes.c @@ -17,7 +17,7 @@ #include "attributes.h" -ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, +ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, "INTERNAL_IP4_ADDRESS", "INTERNAL_IP4_NETMASK", "INTERNAL_IP4_DNS", @@ -36,8 +36,10 @@ ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ "MIP6_HOME_PREFIX", "INTERNAL_IP6_LINK", "INTERNAL_IP6_PREFIX", - "HOME_AGENT_ADDRESS"); -ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS, + "HOME_AGENT_ADDRESS", + "P_CSCF_IP4_ADDRESS", + "P_CSCF_IP6_ADDRESS"); +ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, P_CSCF_IP6_ADDRESS, "XAUTH_TYPE", "XAUTH_USER_NAME", "XAUTH_USER_PASSWORD", @@ -65,7 +67,7 @@ ENUM_NEXT(configuration_attribute_type_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, "UNITY_DDNS_HOSTNAME"); ENUM_END(configuration_attribute_type_names, UNITY_DDNS_HOSTNAME); -ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, +ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, "ADDR", "MASK", "DNS", @@ -84,8 +86,10 @@ ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_ "MIP6HPFX", "LINK6", "PFX6", - "HOA"); -ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS, + "HOA", + "PCSCF4", + "PCSCF6"); +ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, P_CSCF_IP6_ADDRESS, "X_TYPE", "X_USER", "X_PWD", diff --git a/src/libcharon/attributes/attributes.h b/src/libcharon/attributes/attributes.h index 5d1e9f9ba..dd1db4fc3 100644 --- a/src/libcharon/attributes/attributes.h +++ b/src/libcharon/attributes/attributes.h @@ -49,6 +49,9 @@ enum configuration_attribute_type_t { INTERNAL_IP6_LINK = 17, INTERNAL_IP6_PREFIX = 18, HOME_AGENT_ADDRESS = 19, + /* RFC 7651 */ + P_CSCF_IP4_ADDRESS = 20, + P_CSCF_IP6_ADDRESS = 21, /* XAUTH attributes */ XAUTH_TYPE = 16520, XAUTH_USER_NAME = 16521, diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c index 279668249..833c3e950 100644 --- a/src/libcharon/attributes/mem_pool.c +++ b/src/libcharon/attributes/mem_pool.c @@ -17,7 +17,6 @@ #include "mem_pool.h" #include -#include #include #include #include diff --git a/src/libcharon/bus/listeners/custom_logger.h b/src/libcharon/bus/listeners/custom_logger.h new file mode 100644 index 000000000..a256ad1ec --- /dev/null +++ b/src/libcharon/bus/listeners/custom_logger.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 secunet Security Networks AG + * Copyright (C) 2016 Thomas Egerer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup custom_logger custom_logger + * @{ @ingroup listeners + */ + +#ifndef CUSTOM_LOGGER_H_ +#define CUSTOM_LOGGER_H_ + +#include + +typedef struct custom_logger_t custom_logger_t; + +/** + * Custom logger which implements listener_t. + */ +struct custom_logger_t { + + /** + * Implements the logger_t interface. + */ + logger_t logger; + + /** + * Set the loglevel for a debug group. + * + * @param group debug group to set + * @param level max level to log (0..4) + */ + void (*set_level) (custom_logger_t *this, debug_t group, level_t level); + + /** + * Destroy the custom_logger_t object. + */ + void (*destroy) (custom_logger_t *this); +}; + +/** + * Prototype for custom logger construction function pointer. + */ +typedef custom_logger_t *(*custom_logger_constructor_t)(const char *name); + +#endif /** CUSTOM_LOGGER_H_ @}*/ diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index ed7c0d406..3d3c7419b 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2015 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -531,6 +531,57 @@ METHOD(child_cfg_t, install_policy, bool, return this->install_policy; } +#define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; }) +#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); }) + +METHOD(child_cfg_t, equals, bool, + private_child_cfg_t *this, child_cfg_t *other_pub) +{ + private_child_cfg_t *other = (private_child_cfg_t*)other_pub; + + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + if (!this->proposals->equals_offset(this->proposals, other->proposals, + offsetof(proposal_t, equals))) + { + return FALSE; + } + if (!this->my_ts->equals_offset(this->my_ts, other->my_ts, + offsetof(traffic_selector_t, equals))) + { + return FALSE; + } + if (!this->other_ts->equals_offset(this->other_ts, other->other_ts, + offsetof(traffic_selector_t, equals))) + { + return FALSE; + } + return this->hostaccess == other->hostaccess && + this->mode == other->mode && + this->start_action == other->start_action && + this->dpd_action == other->dpd_action && + this->close_action == other->close_action && + LIFETIME_EQUALS(this->lifetime, other->lifetime) && + this->use_ipcomp == other->use_ipcomp && + this->inactivity == other->inactivity && + this->reqid == other->reqid && + this->mark_in.value == other->mark_in.value && + this->mark_in.mask == other->mark_in.mask && + this->mark_out.value == other->mark_out.value && + this->mark_out.mask == other->mark_out.mask && + this->tfc == other->tfc && + this->replay_window == other->replay_window && + this->proxy_mode == other->proxy_mode && + this->install_policy == other->install_policy && + streq(this->updown, other->updown); +} + METHOD(child_cfg_t, get_ref, child_cfg_t*, private_child_cfg_t *this) { @@ -593,6 +644,7 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, .set_replay_window = _set_replay_window, .use_proxy_mode = _use_proxy_mode, .install_policy = _install_policy, + .equals = _equals, .get_ref = _get_ref, .destroy = _destroy, }, diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 9f7a92b70..22641f77e 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2015 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -273,6 +273,14 @@ struct child_cfg_t { */ bool (*install_policy)(child_cfg_t *this); + /** + * Check if two child_cfg objects are equal. + * + * @param other candidate to check for equality against this + * @return TRUE if equal + */ + bool (*equals)(child_cfg_t *this, child_cfg_t *other); + /** * Increase the reference count. * diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index dee9e4c29..a720e1493 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -371,9 +371,6 @@ METHOD(ike_cfg_t, equals, bool, private_ike_cfg_t *this, ike_cfg_t *other_public) { private_ike_cfg_t *other = (private_ike_cfg_t*)other_public; - enumerator_t *e1, *e2; - proposal_t *p1, *p2; - bool eq = TRUE; if (this == other) { @@ -383,25 +380,12 @@ METHOD(ike_cfg_t, equals, bool, { return FALSE; } - if (this->proposals->get_count(this->proposals) != - other->proposals->get_count(other->proposals)) + if (!this->proposals->equals_offset(this->proposals, other->proposals, + offsetof(proposal_t, equals))) { return FALSE; } - e1 = this->proposals->create_enumerator(this->proposals); - e2 = other->proposals->create_enumerator(other->proposals); - while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2)) - { - if (!p1->equals(p1, p2)) - { - eq = FALSE; - break; - } - } - e1->destroy(e1); - e2->destroy(e2); - - return (eq && + return this->version == other->version && this->certreq == other->certreq && this->force_encap == other->force_encap && @@ -409,7 +393,7 @@ METHOD(ike_cfg_t, equals, bool, streq(this->me, other->me) && streq(this->other, other->other) && this->my_port == other->my_port && - this->other_port == other->other_port); + this->other_port == other->other_port; } METHOD(ike_cfg_t, get_ref, ike_cfg_t*, diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index aa2a39ce5..d28a79507 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2008 Tobias Brunner + * Copyright (C) 2007-2015 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -200,6 +200,117 @@ METHOD(peer_cfg_t, add_child_cfg, void, this->mutex->unlock(this->mutex); } +typedef struct { + enumerator_t public; + linked_list_t *removed; + linked_list_t *added; + enumerator_t *wrapped; + bool add; +} child_cfgs_replace_enumerator_t; + +METHOD(enumerator_t, child_cfgs_replace_enumerate, bool, + child_cfgs_replace_enumerator_t *this, child_cfg_t **chd, bool *added) +{ + child_cfg_t *child_cfg; + + if (!this->wrapped) + { + this->wrapped = this->removed->create_enumerator(this->removed); + } + while (TRUE) + { + if (this->wrapped->enumerate(this->wrapped, &child_cfg)) + { + if (chd) + { + *chd = child_cfg; + } + if (added) + { + *added = this->add; + } + return TRUE; + } + if (this->add) + { + break; + } + this->wrapped = this->added->create_enumerator(this->added); + this->add = TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, child_cfgs_replace_enumerator_destroy, void, + child_cfgs_replace_enumerator_t *this) +{ + DESTROY_IF(this->wrapped); + this->removed->destroy_offset(this->removed, offsetof(child_cfg_t, destroy)); + this->added->destroy_offset(this->added, offsetof(child_cfg_t, destroy)); + free(this); +} + +METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*, + private_peer_cfg_t *this, peer_cfg_t *other_pub) +{ + private_peer_cfg_t *other = (private_peer_cfg_t*)other_pub; + linked_list_t *removed, *added; + enumerator_t *mine, *others; + child_cfg_t *my_cfg, *other_cfg; + child_cfgs_replace_enumerator_t *enumerator; + bool found; + + removed = linked_list_create(); + + other->mutex->lock(other->mutex); + added = linked_list_create_from_enumerator( + other->child_cfgs->create_enumerator(other->child_cfgs)); + added->invoke_offset(added, offsetof(child_cfg_t, get_ref)); + other->mutex->unlock(other->mutex); + + this->mutex->lock(this->mutex); + others = added->create_enumerator(added); + mine = this->child_cfgs->create_enumerator(this->child_cfgs); + while (mine->enumerate(mine, &my_cfg)) + { + found = FALSE; + while (others->enumerate(others, &other_cfg)) + { + if (my_cfg->equals(my_cfg, other_cfg)) + { + added->remove_at(added, others); + other_cfg->destroy(other_cfg); + found = TRUE; + break; + } + } + added->reset_enumerator(added, others); + if (!found) + { + this->child_cfgs->remove_at(this->child_cfgs, mine); + removed->insert_last(removed, my_cfg); + } + } + while (others->enumerate(others, &other_cfg)) + { + this->child_cfgs->insert_last(this->child_cfgs, + other_cfg->get_ref(other_cfg)); + } + others->destroy(others); + mine->destroy(mine); + this->mutex->unlock(this->mutex); + + INIT(enumerator, + .public = { + .enumerate = (void*)_child_cfgs_replace_enumerate, + .destroy = (void*)_child_cfgs_replace_enumerator_destroy, + }, + .removed = removed, + .added = added, + ); + return &enumerator->public; +} + /** * child_cfg enumerator */ @@ -538,10 +649,6 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other) METHOD(peer_cfg_t, equals, bool, private_peer_cfg_t *this, private_peer_cfg_t *other) { - enumerator_t *e1, *e2; - host_t *vip1, *vip2; - char *pool1, *pool2; - if (this == other) { return TRUE; @@ -550,44 +657,15 @@ METHOD(peer_cfg_t, equals, bool, { return FALSE; } - - if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips)) + if (!this->vips->equals_offset(this->vips, other->vips, + offsetof(host_t, ip_equals))) { return FALSE; } - e1 = create_virtual_ip_enumerator(this); - e2 = create_virtual_ip_enumerator(other); - if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2)) - { - if (!vip1->ip_equals(vip1, vip2)) - { - e1->destroy(e1); - e2->destroy(e2); - return FALSE; - } - } - e1->destroy(e1); - e2->destroy(e2); - - if (this->pools->get_count(this->pools) != - other->pools->get_count(other->pools)) + if (!this->pools->equals_function(this->pools, other->pools, (void*)streq)) { return FALSE; } - e1 = create_pool_enumerator(this); - e2 = create_pool_enumerator(other); - if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2)) - { - if (!streq(pool1, pool2)) - { - e1->destroy(e1); - e2->destroy(e2); - return FALSE; - } - } - e1->destroy(e1); - e2->destroy(e2); - return ( get_ike_version(this) == get_ike_version(other) && this->cert_policy == other->cert_policy && @@ -666,6 +744,10 @@ peer_cfg_t *peer_cfg_create(char *name, { jitter_time = reauth_time; } + if (dpd && dpd_timeout && dpd > dpd_timeout) + { + dpd_timeout = dpd; + } INIT(this, .public = { @@ -674,6 +756,7 @@ peer_cfg_t *peer_cfg_create(char *name, .get_ike_cfg = _get_ike_cfg, .add_child_cfg = _add_child_cfg, .remove_child_cfg = (void*)_remove_child_cfg, + .replace_child_cfgs = _replace_child_cfgs, .create_child_cfg_enumerator = _create_child_cfg_enumerator, .select_child_cfg = _select_child_cfg, .get_cert_policy = _get_cert_policy, diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index 3e780394a..b612a2ef1 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2008 Tobias Brunner + * Copyright (C) 2007-2015 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -153,6 +153,20 @@ struct peer_cfg_t { */ void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator); + /** + * Replace the CHILD configs with those in the given PEER config. + * + * Configs that are equal are not replaced. + * + * The enumerator enumerates the removed and added CHILD configs + * (child_cfg_t*, bool), where the flag is FALSE for removed configs and + * TRUE for added configs. + * + * @param other other config to get CHILD configs from + * @return an enumerator over removed/added CHILD configs + */ + enumerator_t* (*replace_child_cfgs)(peer_cfg_t *this, peer_cfg_t *other); + /** * Create an enumerator for all attached CHILD configs. * diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index e59dcd9ec..95b6a00ea 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2008-2014 Tobias Brunner * Copyright (C) 2006-2010 Martin Willi + * Copyright (C) 2013-2015 Andreas Steffen * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -640,20 +641,41 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) if (aead) { + /* Round 1 adds algorithms with at least 128 bit security strength */ enumerator = lib->crypto->create_aead_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { switch (encryption) { - case ENCR_AES_CCM_ICV8: - case ENCR_AES_CCM_ICV12: + case ENCR_AES_GCM_ICV16: case ENCR_AES_CCM_ICV16: - case ENCR_AES_GCM_ICV8: + case ENCR_CAMELLIA_CCM_ICV16: + /* we assume that we support all AES/Camellia sizes */ + add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); + add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); + add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); + break; + case ENCR_CHACHA20_POLY1305: + add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 2 adds algorithms with less than 128 bit security strength */ + enumerator = lib->crypto->create_aead_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) + { + switch (encryption) + { case ENCR_AES_GCM_ICV12: - case ENCR_AES_GCM_ICV16: - case ENCR_CAMELLIA_CCM_ICV8: + case ENCR_AES_GCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV8: case ENCR_CAMELLIA_CCM_ICV12: - case ENCR_CAMELLIA_CCM_ICV16: + case ENCR_CAMELLIA_CCM_ICV8: /* we assume that we support all AES/Camellia sizes */ add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); @@ -672,6 +694,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) } else { + /* Round 1 adds algorithms with at least 128 bit security strength */ enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { @@ -686,6 +709,18 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 2 adds algorithms with less than 128 bit security strength */ + enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) + { + switch (encryption) + { case ENCR_3DES: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0); break; @@ -703,18 +738,33 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) return FALSE; } + /* Round 1 adds algorithms with at least 128 bit security strength */ enumerator = lib->crypto->create_signer_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) { switch (integrity) { - case AUTH_HMAC_SHA1_96: case AUTH_HMAC_SHA2_256_128: case AUTH_HMAC_SHA2_384_192: case AUTH_HMAC_SHA2_512_256: - case AUTH_HMAC_MD5_96: + add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 2 adds algorithms with less than 128 bit security strength */ + enumerator = lib->crypto->create_signer_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) + { + switch (integrity) + { case AUTH_AES_XCBC_96: case AUTH_AES_CMAC_96: + case AUTH_HMAC_SHA1_96: + case AUTH_HMAC_MD5_96: add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); break; default: @@ -724,16 +774,15 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) enumerator->destroy(enumerator); } + /* Round 1 adds algorithms with at least 128 bit security strength */ enumerator = lib->crypto->create_prf_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &prf, &plugin_name)) { switch (prf) { - case PRF_HMAC_SHA1: case PRF_HMAC_SHA2_256: case PRF_HMAC_SHA2_384: case PRF_HMAC_SHA2_512: - case PRF_HMAC_MD5: case PRF_AES128_XCBC: case PRF_AES128_CMAC: add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); @@ -744,6 +793,63 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) } enumerator->destroy(enumerator); + /* Round 2 adds algorithms with less than 128 bit security strength */ + enumerator = lib->crypto->create_prf_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &prf, &plugin_name)) + { + switch (prf) + { + case PRF_HMAC_SHA1: + case PRF_HMAC_MD5: + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */ + enumerator = lib->crypto->create_dh_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &group, &plugin_name)) + { + switch (group) + { + case ECP_256_BIT: + case ECP_384_BIT: + case ECP_521_BIT: + case ECP_256_BP: + case ECP_384_BP: + case ECP_512_BP: + case NTRU_128_BIT: + case NTRU_192_BIT: + case NTRU_256_BIT: + add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 2 adds other algorithms with at least 128 bit security strength */ + enumerator = lib->crypto->create_dh_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &group, &plugin_name)) + { + switch (group) + { + case MODP_3072_BIT: + case MODP_4096_BIT: + case MODP_8192_BIT: + add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* Round 3 adds algorithms with less than 128 bit security strength */ enumerator = lib->crypto->create_dh_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &group, &plugin_name)) { @@ -755,28 +861,16 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) case MODP_768_BIT: /* weak */ break; - case MODP_1024_BIT: - case MODP_1536_BIT: case MODP_2048_BIT: - case MODP_3072_BIT: - case MODP_4096_BIT: - case MODP_8192_BIT: - case ECP_256_BIT: - case ECP_384_BIT: - case ECP_521_BIT: - case MODP_1024_160: - case MODP_2048_224: case MODP_2048_256: - case ECP_192_BIT: + case MODP_2048_224: + case MODP_1536_BIT: + case MODP_1024_BIT: + case MODP_1024_160: case ECP_224_BIT: case ECP_224_BP: - case ECP_256_BP: - case ECP_384_BP: - case ECP_512_BP: + case ECP_192_BIT: case NTRU_112_BIT: - case NTRU_128_BIT: - case NTRU_192_BIT: - case NTRU_256_BIT: add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); break; default: @@ -805,21 +899,27 @@ proposal_t *proposal_create_default(protocol_id_t protocol) } break; case PROTO_ESP: - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); break; case PROTO_AH: - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); break; default: break; diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index dce2a7144..cef8b8992 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -16,6 +16,29 @@ * for more details. */ +/* + * Copyright (C) 2016 secunet Security Networks AG + * Copyright (C) 2016 Thomas Egerer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + #include #include #include @@ -110,6 +133,70 @@ static void dbg_bus(debug_t group, level_t level, char *fmt, ...) va_end(args); } +/** + * Data for registered custom loggers + */ +typedef struct { + /** + * Name of the custom logger (also used for loglevel configuration) + */ + char *name; + + /** + * Constructor to be called for custom logger creation + */ + custom_logger_constructor_t constructor; + +} custom_logger_entry_t; + +#define MAX_CUSTOM_LOGGERS 10 + +/** + * Static array for logger registration using __attribute__((constructor)) + */ +static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS]; +static int custom_logger_count; + +/** + * Described in header + */ +void register_custom_logger(char *name, + custom_logger_constructor_t constructor) +{ + if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1) + { + custom_loggers[custom_logger_count].name = name; + custom_loggers[custom_logger_count].constructor = constructor; + custom_logger_count++; + } + else + { + fprintf(stderr, "failed to register custom logger, please increase " + "MAX_CUSTOM_LOGGERS"); + } +} + +/** + * Types of supported loggers + */ +typedef enum { + /** + * Syslog logger instance + */ + SYS_LOGGER, + + /** + * File logger instance + */ + FILE_LOGGER, + + /** + * Custom logger instance + */ + CUSTOM_LOGGER, + +} logger_type_t; + /** * Some metadata about configured loggers */ @@ -120,9 +207,9 @@ typedef struct { char *target; /** - * TRUE if this is a file logger + * Type of logger */ - bool file; + logger_type_t type; /** * The actual logger @@ -130,6 +217,7 @@ typedef struct { union { sys_logger_t *sys; file_logger_t *file; + custom_logger_t *custom; } logger; } logger_entry_t; @@ -139,13 +227,17 @@ typedef struct { */ static void logger_entry_destroy(logger_entry_t *this) { - if (this->file) - { - DESTROY_IF(this->logger.file); - } - else + switch (this->type) { - DESTROY_IF(this->logger.sys); + case FILE_LOGGER: + DESTROY_IF(this->logger.file); + break; + case SYS_LOGGER: + DESTROY_IF(this->logger.sys); + break; + case CUSTOM_LOGGER: + DESTROY_IF(this->logger.custom); + break; } free(this->target); free(this); @@ -156,13 +248,18 @@ static void logger_entry_destroy(logger_entry_t *this) */ static void logger_entry_unregister_destroy(logger_entry_t *this) { - if (this->file) + switch (this->type) { - charon->bus->remove_logger(charon->bus, &this->logger.file->logger); - } - else - { - charon->bus->remove_logger(charon->bus, &this->logger.sys->logger); + case FILE_LOGGER: + charon->bus->remove_logger(charon->bus, &this->logger.file->logger); + break; + case SYS_LOGGER: + charon->bus->remove_logger(charon->bus, &this->logger.sys->logger); + break; + case CUSTOM_LOGGER: + charon->bus->remove_logger(charon->bus, + &this->logger.custom->logger); + break; } logger_entry_destroy(this); } @@ -170,9 +267,10 @@ static void logger_entry_unregister_destroy(logger_entry_t *this) /** * Match a logger entry by target and whether it is a file or syslog logger */ -static bool logger_entry_match(logger_entry_t *this, char *target, bool *file) +static bool logger_entry_match(logger_entry_t *this, char *target, + logger_type_t *type) { - return this->file == *file && streq(this->target, target); + return this->type == *type && streq(this->target, target); } /** @@ -228,28 +326,45 @@ static int get_syslog_facility(char *facility) * Returns an existing or newly created logger entry (if found, it is removed * from the given linked list of existing loggers) */ -static logger_entry_t *get_logger_entry(char *target, bool is_file_logger, - linked_list_t *existing) +static logger_entry_t *get_logger_entry(char *target, logger_type_t type, + linked_list_t *existing, + custom_logger_constructor_t constructor) { logger_entry_t *entry; if (existing->find_first(existing, (void*)logger_entry_match, - (void**)&entry, target, &is_file_logger) != SUCCESS) + (void**)&entry, target, &type) != SUCCESS) { INIT(entry, .target = strdup(target), - .file = is_file_logger, + .type = type, ); - if (is_file_logger) + switch (type) { - entry->logger.file = file_logger_create(target); - } + case FILE_LOGGER: + entry->logger.file = file_logger_create(target); + break; + case SYS_LOGGER: #ifdef HAVE_SYSLOG - else - { - entry->logger.sys = sys_logger_create(get_syslog_facility(target)); - } + entry->logger.sys = sys_logger_create( + get_syslog_facility(target)); + break; +#else + free(entry); + return NULL; #endif /* HAVE_SYSLOG */ + case CUSTOM_LOGGER: + if (constructor) + { + entry->logger.custom = constructor(target); + } + if (!entry->logger.custom) + { + free(entry); + return NULL; + } + break; + } } else { @@ -266,9 +381,12 @@ static sys_logger_t *add_sys_logger(private_daemon_t *this, char *facility, { logger_entry_t *entry; - entry = get_logger_entry(facility, FALSE, current_loggers); - this->loggers->insert_last(this->loggers, entry); - return entry->logger.sys; + entry = get_logger_entry(facility, SYS_LOGGER, current_loggers, NULL); + if (entry) + { + this->loggers->insert_last(this->loggers, entry); + } + return entry ? entry->logger.sys : NULL; } /** @@ -279,9 +397,30 @@ static file_logger_t *add_file_logger(private_daemon_t *this, char *filename, { logger_entry_t *entry; - entry = get_logger_entry(filename, TRUE, current_loggers); - this->loggers->insert_last(this->loggers, entry); - return entry->logger.file; + entry = get_logger_entry(filename, FILE_LOGGER, current_loggers, NULL); + if (entry) + { + this->loggers->insert_last(this->loggers, entry); + } + return entry ? entry->logger.file : NULL; +} + + /** + * Create or reuse a custom logger + */ +static custom_logger_t *add_custom_logger(private_daemon_t *this, + custom_logger_entry_t *custom, + linked_list_t *current_loggers) +{ + logger_entry_t *entry; + + entry = get_logger_entry(custom->name, CUSTOM_LOGGER, current_loggers, + custom->constructor); + if (entry) + { + this->loggers->insert_last(this->loggers, entry); + } + return entry ? entry->logger.custom : NULL; } /** @@ -300,6 +439,11 @@ static void load_sys_logger(private_daemon_t *this, char *facility, } sys_logger = add_sys_logger(this, facility, current_loggers); + if (!sys_logger) + { + return; + } + sys_logger->set_options(sys_logger, lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name", FALSE, lib->ns, facility)); @@ -339,6 +483,11 @@ static void load_file_logger(private_daemon_t *this, char *filename, "%s.filelog.%s.append", TRUE, lib->ns, filename); file_logger = add_file_logger(this, filename, current_loggers); + if (!file_logger) + { + return; + } + file_logger->set_options(file_logger, time_format, add_ms, ike_name); file_logger->open(file_logger, flush_line, append); @@ -353,12 +502,41 @@ static void load_file_logger(private_daemon_t *this, char *filename, charon->bus->add_logger(charon->bus, &file_logger->logger); } +/** + * Load the given custom logger configured in strongswan.conf + */ +static void load_custom_logger(private_daemon_t *this, + custom_logger_entry_t *entry, + linked_list_t *current_loggers) +{ + custom_logger_t *custom_logger; + debug_t group; + level_t def; + + custom_logger = add_custom_logger(this, entry, current_loggers); + if (!custom_logger) + { + return; + } + + def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1, + lib->ns, entry->name); + for (group = 0; group < DBG_MAX; group++) + { + custom_logger->set_level(custom_logger, group, + lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def, + lib->ns, entry->name, debug_lower_names, group)); + } + charon->bus->add_logger(charon->bus, &custom_logger->logger); +} + METHOD(daemon_t, load_loggers, void, private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr) { enumerator_t *enumerator; linked_list_t *current_loggers; char *target; + int i; this->mutex->lock(this->mutex); handle_syslog_identifier(this); @@ -380,6 +558,11 @@ METHOD(daemon_t, load_loggers, void, } enumerator->destroy(enumerator); + for (i = 0; i < custom_logger_count; ++i) + { + load_custom_logger(this, &custom_loggers[i], current_loggers); + } + if (!this->loggers->get_count(this->loggers) && levels) { /* setup legacy style default loggers configured via command-line */ file_logger_t *file_logger; @@ -431,15 +614,24 @@ METHOD(daemon_t, set_level, void, enumerator = this->loggers->create_enumerator(this->loggers); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->file) - { - entry->logger.file->set_level(entry->logger.file, group, level); - charon->bus->add_logger(charon->bus, &entry->logger.file->logger); - } - else + switch (entry->type) { - entry->logger.sys->set_level(entry->logger.sys, group, level); - charon->bus->add_logger(charon->bus, &entry->logger.sys->logger); + case FILE_LOGGER: + entry->logger.file->set_level(entry->logger.file, group, level); + charon->bus->add_logger(charon->bus, + &entry->logger.file->logger); + break; + case SYS_LOGGER: + entry->logger.sys->set_level(entry->logger.sys, group, level); + charon->bus->add_logger(charon->bus, + &entry->logger.sys->logger); + break; + case CUSTOM_LOGGER: + entry->logger.custom->set_level(entry->logger.custom, group, + level); + charon->bus->add_logger(charon->bus, + &entry->logger.sys->logger); + break; } } enumerator->destroy(enumerator); @@ -488,11 +680,13 @@ static void destroy(private_daemon_t *this) DESTROY_IF(this->kernel_handler); DESTROY_IF(this->public.traps); DESTROY_IF(this->public.shunts); + DESTROY_IF(this->public.redirect); DESTROY_IF(this->public.controller); DESTROY_IF(this->public.eap); DESTROY_IF(this->public.xauth); DESTROY_IF(this->public.backends); DESTROY_IF(this->public.socket); + DESTROY_IF(this->public.kernel); /* rehook library logging, shutdown logging */ dbg = dbg_old; @@ -670,6 +864,7 @@ private_daemon_t *daemon_create() .ref = 1, ); charon = &this->public; + this->public.kernel = kernel_interface_create(); this->public.attributes = attribute_manager_create(); this->public.controller = controller_create(); this->public.eap = eap_manager_create(); @@ -678,6 +873,7 @@ private_daemon_t *daemon_create() this->public.socket = socket_manager_create(); this->public.traps = trap_manager_create(); this->public.shunts = shunt_manager_create(); + this->public.redirect = redirect_manager_create(); this->kernel_handler = kernel_handler_create(); return this; diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h index d16bf1ddb..48b9c7ec3 100644 --- a/src/libcharon/daemon.h +++ b/src/libcharon/daemon.h @@ -16,6 +16,29 @@ * for more details. */ +/* + * Copyright (C) 2016 secunet Security Networks AG + * Copyright (C) 2016 Thomas Egerer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + /** * @defgroup libcharon libcharon * @@ -40,7 +63,7 @@ * @defgroup payloads payloads * @ingroup encoding * - * @defgroup ckernel kernel + * @defgroup kernel kernel * @ingroup libcharon * * @defgroup network network @@ -156,15 +179,18 @@ typedef struct daemon_t daemon_t; #include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -214,6 +240,11 @@ struct daemon_t { */ socket_manager_t *socket; + /** + * Kernel interface to communicate with kernel + */ + kernel_interface_t *kernel; + /** * A ike_sa_manager_t instance. */ @@ -234,6 +265,11 @@ struct daemon_t { */ shunt_manager_t *shunts; + /** + * Manager for IKE redirect providers + */ + redirect_manager_t *redirect; + /** * Manager for the different configuration backends. */ @@ -311,8 +347,8 @@ struct daemon_t { bool to_stderr); /** - * Set the log level for the given log group for all configured file- and - * syslog-loggers. + * Set the log level for the given log group for all configured file-, + * syslog and custom-loggers. * * @param group log group * @param level log level @@ -345,4 +381,15 @@ bool libcharon_init(); */ void libcharon_deinit(); +/** + * Register a custom logger constructor. + * + * To be called from __attribute__((constructor)) functions. + * + * @param name name of the logger (also used for loglevel config) + * @param constructor constructor to create custom logger + */ +void register_custom_logger(char *name, + custom_logger_constructor_t constructor); + #endif /** DAEMON_H_ @}*/ diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 3303024cd..bbdc4629d 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -551,13 +551,13 @@ static payload_order_t aggressive_i_order[] = { {PLV1_NONCE, 0}, {PLV1_ID, 0}, {PLV1_CERTIFICATE, 0}, + {PLV1_CERTREQ, 0}, + {PLV1_NOTIFY, 0}, + {PLV1_VENDOR_ID, 0}, {PLV1_NAT_D, 0}, {PLV1_NAT_D_DRAFT_00_03, 0}, {PLV1_SIGNATURE, 0}, {PLV1_HASH, 0}, - {PLV1_CERTREQ, 0}, - {PLV1_NOTIFY, 0}, - {PLV1_VENDOR_ID, 0}, {PLV1_FRAGMENT, 0}, }; @@ -591,13 +591,13 @@ static payload_order_t aggressive_r_order[] = { {PLV1_NONCE, 0}, {PLV1_ID, 0}, {PLV1_CERTIFICATE, 0}, + {PLV1_CERTREQ, 0}, + {PLV1_NOTIFY, 0}, + {PLV1_VENDOR_ID, 0}, {PLV1_NAT_D, 0}, {PLV1_NAT_D_DRAFT_00_03, 0}, {PLV1_SIGNATURE, 0}, {PLV1_HASH, 0}, - {PLV1_CERTREQ, 0}, - {PLV1_NOTIFY, 0}, - {PLV1_VENDOR_ID, 0}, {PLV1_FRAGMENT, 0}, }; diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c index 481bb7bc6..4ecdf569d 100644 --- a/src/libcharon/encoding/payloads/configuration_attribute.c +++ b/src/libcharon/encoding/payloads/configuration_attribute.c @@ -132,6 +132,7 @@ METHOD(payload_t, verify, status_t, case INTERNAL_IP4_NBNS: case INTERNAL_ADDRESS_EXPIRY: case INTERNAL_IP4_DHCP: + case P_CSCF_IP4_ADDRESS: if (this->length_or_value != 0 && this->length_or_value != 4) { failed = TRUE; @@ -144,6 +145,13 @@ METHOD(payload_t, verify, status_t, } break; case INTERNAL_IP6_ADDRESS: + if (this->type == PLV1_CONFIGURATION_ATTRIBUTE && + this->length_or_value == 16) + { /* 16 bytes are correct for IKEv1, but older releases sent a + * prefix byte so we still accept 0 or 17 as in IKEv2 */ + break; + } + /* fall-through */ case INTERNAL_IP6_SUBNET: if (this->length_or_value != 0 && this->length_or_value != 17) { @@ -153,6 +161,7 @@ METHOD(payload_t, verify, status_t, case INTERNAL_IP6_DNS: case INTERNAL_IP6_NBNS: case INTERNAL_IP6_DHCP: + case P_CSCF_IP6_ADDRESS: if (this->length_or_value != 0 && this->length_or_value != 16) { failed = TRUE; diff --git a/src/libcharon/kernel/kernel_handler.c b/src/libcharon/kernel/kernel_handler.c index 9c0e2602b..be37d30e5 100644 --- a/src/libcharon/kernel/kernel_handler.c +++ b/src/libcharon/kernel/kernel_handler.c @@ -15,7 +15,6 @@ #include "kernel_handler.h" -#include #include #include #include @@ -135,8 +134,7 @@ METHOD(kernel_listener_t, roam, bool, METHOD(kernel_handler_t, destroy, void, private_kernel_handler_t *this) { - hydra->kernel_interface->remove_listener(hydra->kernel_interface, - &this->public.listener); + charon->kernel->remove_listener(charon->kernel, &this->public.listener); free(this); } @@ -157,8 +155,7 @@ kernel_handler_t *kernel_handler_create() }, ); - hydra->kernel_interface->add_listener(hydra->kernel_interface, - &this->public.listener); + charon->kernel->add_listener(charon->kernel, &this->public.listener); return &this->public; } diff --git a/src/libcharon/kernel/kernel_handler.h b/src/libcharon/kernel/kernel_handler.h index 48ad6889c..f1fa0bdfc 100644 --- a/src/libcharon/kernel/kernel_handler.h +++ b/src/libcharon/kernel/kernel_handler.h @@ -15,7 +15,7 @@ /** * @defgroup kernel_handler kernel_handler - * @{ @ingroup ckernel + * @{ @ingroup kernel */ #ifndef KERNEL_HANDLER_H_ diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c new file mode 100644 index 000000000..40c4ee589 --- /dev/null +++ b/src/libcharon/kernel/kernel_interface.c @@ -0,0 +1,1085 @@ +/* + * Copyright (C) 2008-2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/* + * Copyright (c) 2012 Nanoteq Pty Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "kernel_interface.h" + +#include +#include +#include +#include +#include + +typedef struct private_kernel_interface_t private_kernel_interface_t; + +typedef struct kernel_algorithm_t kernel_algorithm_t; + +/** + * Mapping of IKE algorithms to kernel-specific algorithm identifiers + */ +struct kernel_algorithm_t { + + /** + * Transform type of the algorithm + */ + transform_type_t type; + + /** + * Identifier specified in IKE + */ + u_int16_t ike; + + /** + * Identifier as defined in pfkeyv2.h + */ + u_int16_t kernel; + + /** + * Name of the algorithm in linux crypto API + */ + char *name; +}; + +/** + * Private data of a kernel_interface_t object. + */ +struct private_kernel_interface_t { + + /** + * Public part of kernel_interface_t object. + */ + kernel_interface_t public; + + /** + * Registered IPsec constructor + */ + kernel_ipsec_constructor_t ipsec_constructor; + + /** + * Registered net constructor + */ + kernel_net_constructor_t net_constructor; + + /** + * ipsec interface + */ + kernel_ipsec_t *ipsec; + + /** + * network interface + */ + kernel_net_t *net; + + /** + * mutex for listeners + */ + mutex_t *mutex; + + /** + * list of registered listeners + */ + linked_list_t *listeners; + + /** + * Reqid entries indexed by reqids + */ + hashtable_t *reqids; + + /** + * Reqid entries indexed by traffic selectors + */ + hashtable_t *reqids_by_ts; + + /** + * mutex for algorithm mappings + */ + mutex_t *mutex_algs; + + /** + * List of algorithm mappings (kernel_algorithm_t*) + */ + linked_list_t *algorithms; + + /** + * List of interface names to include or exclude (char*), NULL if interfaces + * are not filtered + */ + linked_list_t *ifaces_filter; + + /** + * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider + * only those listed there + */ + bool ifaces_exclude; +}; + +METHOD(kernel_interface_t, get_features, kernel_feature_t, + private_kernel_interface_t *this) +{ + kernel_feature_t features = 0; + + if (this->ipsec && this->ipsec->get_features) + { + features |= this->ipsec->get_features(this->ipsec); + } + if (this->net && this->net->get_features) + { + features |= this->net->get_features(this->net); + } + return features; +} + +METHOD(kernel_interface_t, get_spi, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t *spi) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->get_spi(this->ipsec, src, dst, protocol, spi); +} + +METHOD(kernel_interface_t, get_cpi, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + u_int16_t *cpi) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->get_cpi(this->ipsec, src, dst, cpi); +} + +/** + * Reqid mapping entry + */ +typedef struct { + /** allocated reqid */ + u_int32_t reqid; + /** references to this entry */ + u_int refs; + /** inbound mark used for SA */ + mark_t mark_in; + /** outbound mark used for SA */ + mark_t mark_out; + /** local traffic selectors */ + array_t *local; + /** remote traffic selectors */ + array_t *remote; +} reqid_entry_t; + +/** + * Destroy a reqid mapping entry + */ +static void reqid_entry_destroy(reqid_entry_t *entry) +{ + array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy)); + array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy)); + free(entry); +} + +/** + * Hashtable hash function for reqid entries using reqid as key + */ +static u_int hash_reqid(reqid_entry_t *entry) +{ + return chunk_hash_inc(chunk_from_thing(entry->reqid), + chunk_hash_inc(chunk_from_thing(entry->mark_in), + chunk_hash(chunk_from_thing(entry->mark_out)))); +} + +/** + * Hashtable equals function for reqid entries using reqid as key + */ +static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b) +{ + return a->reqid == b->reqid && + a->mark_in.value == b->mark_in.value && + a->mark_in.mask == b->mark_in.mask && + a->mark_out.value == b->mark_out.value && + a->mark_out.mask == b->mark_out.mask; +} + +/** + * Hash an array of traffic selectors + */ +static u_int hash_ts_array(array_t *array, u_int hash) +{ + enumerator_t *enumerator; + traffic_selector_t *ts; + + enumerator = array_create_enumerator(array); + while (enumerator->enumerate(enumerator, &ts)) + { + hash = ts->hash(ts, hash); + } + enumerator->destroy(enumerator); + + return hash; +} + +/** + * Hashtable hash function for reqid entries using traffic selectors as key + */ +static u_int hash_reqid_by_ts(reqid_entry_t *entry) +{ + return hash_ts_array(entry->local, hash_ts_array(entry->remote, + chunk_hash_inc(chunk_from_thing(entry->mark_in), + chunk_hash(chunk_from_thing(entry->mark_out))))); +} + +/** + * Compare two array with traffic selectors for equality + */ +static bool ts_array_equals(array_t *a, array_t *b) +{ + traffic_selector_t *tsa, *tsb; + enumerator_t *ae, *be; + bool equal = TRUE; + + if (array_count(a) != array_count(b)) + { + return FALSE; + } + + ae = array_create_enumerator(a); + be = array_create_enumerator(b); + while (equal && ae->enumerate(ae, &tsa) && be->enumerate(be, &tsb)) + { + equal = tsa->equals(tsa, tsb); + } + ae->destroy(ae); + be->destroy(be); + + return equal; +} + +/** + * Hashtable equals function for reqid entries using traffic selectors as key + */ +static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b) +{ + return ts_array_equals(a->local, b->local) && + ts_array_equals(a->remote, b->remote) && + a->mark_in.value == b->mark_in.value && + a->mark_in.mask == b->mark_in.mask && + a->mark_out.value == b->mark_out.value && + a->mark_out.mask == b->mark_out.mask; +} + +/** + * Create an array from copied traffic selector list items + */ +static array_t *array_from_ts_list(linked_list_t *list) +{ + enumerator_t *enumerator; + traffic_selector_t *ts; + array_t *array; + + array = array_create(0, 0); + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &ts)) + { + array_insert(array, ARRAY_TAIL, ts->clone(ts)); + } + enumerator->destroy(enumerator); + + return array; +} + +METHOD(kernel_interface_t, alloc_reqid, status_t, + private_kernel_interface_t *this, + linked_list_t *local_ts, linked_list_t *remote_ts, + mark_t mark_in, mark_t mark_out, u_int32_t *reqid) +{ + static u_int32_t counter = 0; + reqid_entry_t *entry = NULL, *tmpl; + status_t status = SUCCESS; + + INIT(tmpl, + .local = array_from_ts_list(local_ts), + .remote = array_from_ts_list(remote_ts), + .mark_in = mark_in, + .mark_out = mark_out, + .reqid = *reqid, + ); + + this->mutex->lock(this->mutex); + if (tmpl->reqid) + { + /* search by reqid if given */ + entry = this->reqids->get(this->reqids, tmpl); + } + if (entry) + { + /* we don't require a traffic selector match for explicit reqids, + * as we wan't to reuse a reqid for trap-triggered policies that + * got narrowed during negotiation. */ + reqid_entry_destroy(tmpl); + } + else + { + /* search by traffic selectors */ + entry = this->reqids_by_ts->get(this->reqids_by_ts, tmpl); + if (entry) + { + reqid_entry_destroy(tmpl); + } + else + { + /* none found, create a new entry, allocating a reqid */ + entry = tmpl; + entry->reqid = ++counter; + this->reqids_by_ts->put(this->reqids_by_ts, entry, entry); + this->reqids->put(this->reqids, entry, entry); + } + *reqid = entry->reqid; + } + entry->refs++; + this->mutex->unlock(this->mutex); + + return status; +} + +METHOD(kernel_interface_t, release_reqid, status_t, + private_kernel_interface_t *this, u_int32_t reqid, + mark_t mark_in, mark_t mark_out) +{ + reqid_entry_t *entry, tmpl = { + .reqid = reqid, + .mark_in = mark_in, + .mark_out = mark_out, + }; + + this->mutex->lock(this->mutex); + entry = this->reqids->remove(this->reqids, &tmpl); + if (entry) + { + if (--entry->refs == 0) + { + entry = this->reqids_by_ts->remove(this->reqids_by_ts, entry); + if (entry) + { + reqid_entry_destroy(entry); + } + } + else + { + this->reqids->put(this->reqids, entry, entry); + } + } + this->mutex->unlock(this->mutex); + + if (entry) + { + return SUCCESS; + } + return NOT_FOUND; +} + +METHOD(kernel_interface_t, add_sa, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, + u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid, + mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode, + ipcomp, cpi, replay_window, initiator, encap, esn, inbound, + update, src_ts, dst_ts); +} + +METHOD(kernel_interface_t, update_sa, status_t, + private_kernel_interface_t *this, u_int32_t spi, u_int8_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, + bool encap, bool new_encap, mark_t mark) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst, + new_src, new_dst, encap, new_encap, mark); +} + +METHOD(kernel_interface_t, query_sa, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, + u_int64_t *bytes, u_int64_t *packets, time_t *time) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark, + bytes, packets, time); +} + +METHOD(kernel_interface_t, del_sa, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, + u_int8_t protocol, u_int16_t cpi, mark_t mark) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark); +} + +METHOD(kernel_interface_t, flush_sas, status_t, + private_kernel_interface_t *this) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->flush_sas(this->ipsec); +} + +METHOD(kernel_interface_t, add_policy, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts, + direction, type, sa, mark, priority); +} + +METHOD(kernel_interface_t, query_policy, status_t, + private_kernel_interface_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + time_t *use_time) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts, + direction, mark, use_time); +} + +METHOD(kernel_interface_t, del_policy, status_t, + private_kernel_interface_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts, + direction, type, sa, mark, priority); +} + +METHOD(kernel_interface_t, flush_policies, status_t, + private_kernel_interface_t *this) +{ + if (!this->ipsec) + { + return NOT_SUPPORTED; + } + return this->ipsec->flush_policies(this->ipsec); +} + +METHOD(kernel_interface_t, get_source_addr, host_t*, + private_kernel_interface_t *this, host_t *dest, host_t *src) +{ + if (!this->net) + { + return NULL; + } + return this->net->get_source_addr(this->net, dest, src); +} + +METHOD(kernel_interface_t, get_nexthop, host_t*, + private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src) +{ + if (!this->net) + { + return NULL; + } + return this->net->get_nexthop(this->net, dest, prefix, src); +} + +METHOD(kernel_interface_t, get_interface, bool, + private_kernel_interface_t *this, host_t *host, char **name) +{ + if (!this->net) + { + return NULL; + } + return this->net->get_interface(this->net, host, name); +} + +METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*, + private_kernel_interface_t *this, kernel_address_type_t which) +{ + if (!this->net) + { + return enumerator_create_empty(); + } + return this->net->create_address_enumerator(this->net, which); +} + +METHOD(kernel_interface_t, add_ip, status_t, + private_kernel_interface_t *this, host_t *virtual_ip, int prefix, + char *iface) +{ + if (!this->net) + { + return NOT_SUPPORTED; + } + return this->net->add_ip(this->net, virtual_ip, prefix, iface); +} + +METHOD(kernel_interface_t, del_ip, status_t, + private_kernel_interface_t *this, host_t *virtual_ip, int prefix, bool wait) +{ + if (!this->net) + { + return NOT_SUPPORTED; + } + return this->net->del_ip(this->net, virtual_ip, prefix, wait); +} + +METHOD(kernel_interface_t, add_route, status_t, + private_kernel_interface_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name) +{ + if (!this->net) + { + return NOT_SUPPORTED; + } + return this->net->add_route(this->net, dst_net, prefixlen, gateway, + src_ip, if_name); +} + +METHOD(kernel_interface_t, del_route, status_t, + private_kernel_interface_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name) +{ + if (!this->net) + { + return NOT_SUPPORTED; + } + return this->net->del_route(this->net, dst_net, prefixlen, gateway, + src_ip, if_name); +} + +METHOD(kernel_interface_t, bypass_socket, bool, + private_kernel_interface_t *this, int fd, int family) +{ + if (!this->ipsec) + { + return FALSE; + } + return this->ipsec->bypass_socket(this->ipsec, fd, family); +} + +METHOD(kernel_interface_t, enable_udp_decap, bool, + private_kernel_interface_t *this, int fd, int family, u_int16_t port) +{ + if (!this->ipsec) + { + return FALSE; + } + return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port); +} + +METHOD(kernel_interface_t, is_interface_usable, bool, + private_kernel_interface_t *this, const char *iface) +{ + status_t expected; + + if (!this->ifaces_filter) + { + return TRUE; + } + expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS; + return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq, + NULL, iface) == expected; +} + +METHOD(kernel_interface_t, all_interfaces_usable, bool, + private_kernel_interface_t *this) +{ + return this->ifaces_filter == NULL; +} + +METHOD(kernel_interface_t, get_address_by_ts, status_t, + private_kernel_interface_t *this, traffic_selector_t *ts, + host_t **ip, bool *vip) +{ + enumerator_t *addrs; + host_t *host; + int family; + bool found = FALSE; + + DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts); + + /* if we have a family which includes localhost, we do not + * search for an IP, we use the default */ + family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + + if (family == AF_INET) + { + host = host_create_from_string("127.0.0.1", 0); + } + else + { + host = host_create_from_string("::1", 0); + } + + if (ts->includes(ts, host)) + { + *ip = host_create_any(family); + host->destroy(host); + DBG2(DBG_KNL, "using host %H", *ip); + return SUCCESS; + } + host->destroy(host); + + /* try virtual IPs only first (on all interfaces) */ + addrs = create_address_enumerator(this, + ADDR_TYPE_ALL ^ ADDR_TYPE_REGULAR); + while (addrs->enumerate(addrs, (void**)&host)) + { + if (ts->includes(ts, host)) + { + found = TRUE; + *ip = host->clone(host); + if (vip) + { + *vip = TRUE; + } + break; + } + } + addrs->destroy(addrs); + + if (!found) + { /* then try the regular addresses (on all interfaces) */ + addrs = create_address_enumerator(this, + ADDR_TYPE_ALL ^ ADDR_TYPE_VIRTUAL); + while (addrs->enumerate(addrs, (void**)&host)) + { + if (ts->includes(ts, host)) + { + found = TRUE; + *ip = host->clone(host); + if (vip) + { + *vip = FALSE; + } + break; + } + } + addrs->destroy(addrs); + } + + if (!found) + { + DBG2(DBG_KNL, "no local address found in traffic selector %R", ts); + return FAILED; + } + + DBG2(DBG_KNL, "using host %H", *ip); + return SUCCESS; +} + + +METHOD(kernel_interface_t, add_ipsec_interface, bool, + private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor) +{ + if (!this->ipsec) + { + this->ipsec_constructor = constructor; + this->ipsec = constructor(); + return this->ipsec != NULL; + } + return FALSE; +} + +METHOD(kernel_interface_t, remove_ipsec_interface, bool, + private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor) +{ + if (constructor == this->ipsec_constructor && this->ipsec) + { + this->ipsec->destroy(this->ipsec); + this->ipsec = NULL; + return TRUE; + } + return FALSE; +} + +METHOD(kernel_interface_t, add_net_interface, bool, + private_kernel_interface_t *this, kernel_net_constructor_t constructor) +{ + if (!this->net) + { + this->net_constructor = constructor; + this->net = constructor(); + return this->net != NULL; + } + return FALSE; +} + +METHOD(kernel_interface_t, remove_net_interface, bool, + private_kernel_interface_t *this, kernel_net_constructor_t constructor) +{ + if (constructor == this->net_constructor && this->net) + { + this->net->destroy(this->net); + this->net = NULL; + return TRUE; + } + return FALSE; +} + +METHOD(kernel_interface_t, add_listener, void, + private_kernel_interface_t *this, kernel_listener_t *listener) +{ + this->mutex->lock(this->mutex); + this->listeners->insert_last(this->listeners, listener); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, remove_listener, void, + private_kernel_interface_t *this, kernel_listener_t *listener) +{ + this->mutex->lock(this->mutex); + this->listeners->remove(this->listeners, listener, NULL); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, acquire, void, + private_kernel_interface_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts) +{ + kernel_listener_t *listener; + enumerator_t *enumerator; + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->acquire && + !listener->acquire(listener, reqid, src_ts, dst_ts)) + { + this->listeners->remove_at(this->listeners, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, expire, void, + private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, bool hard) +{ + kernel_listener_t *listener; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->expire && + !listener->expire(listener, protocol, spi, dst, hard)) + { + this->listeners->remove_at(this->listeners, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, mapping, void, + private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, host_t *remote) +{ + kernel_listener_t *listener; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->mapping && + !listener->mapping(listener, protocol, spi, dst, remote)) + { + this->listeners->remove_at(this->listeners, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, migrate, void, + private_kernel_interface_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, host_t *local, host_t *remote) +{ + kernel_listener_t *listener; + enumerator_t *enumerator; + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->migrate && + !listener->migrate(listener, reqid, src_ts, dst_ts, direction, + local, remote)) + { + this->listeners->remove_at(this->listeners, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +static bool call_roam(kernel_listener_t *listener, bool *roam) +{ + return listener->roam && !listener->roam(listener, *roam); +} + +METHOD(kernel_interface_t, roam, void, + private_kernel_interface_t *this, bool address) +{ + this->mutex->lock(this->mutex); + this->listeners->remove(this->listeners, &address, (void*)call_roam); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, tun, void, + private_kernel_interface_t *this, tun_device_t *tun, bool created) +{ + kernel_listener_t *listener; + enumerator_t *enumerator; + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->tun && + !listener->tun(listener, tun, created)) + { + this->listeners->remove_at(this->listeners, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(kernel_interface_t, register_algorithm, void, + private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type, + u_int16_t kernel_id, char *kernel_name) +{ + kernel_algorithm_t *algorithm; + + INIT(algorithm, + .type = type, + .ike = alg_id, + .kernel = kernel_id, + .name = strdup(kernel_name), + ); + + this->mutex_algs->lock(this->mutex_algs); + this->algorithms->insert_first(this->algorithms, algorithm); + this->mutex_algs->unlock(this->mutex_algs); +} + +METHOD(kernel_interface_t, lookup_algorithm, bool, + private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type, + u_int16_t *kernel_id, char **kernel_name) +{ + kernel_algorithm_t *algorithm; + enumerator_t *enumerator; + bool found = FALSE; + + this->mutex_algs->lock(this->mutex_algs); + enumerator = this->algorithms->create_enumerator(this->algorithms); + while (enumerator->enumerate(enumerator, &algorithm)) + { + if (algorithm->type == type && algorithm->ike == alg_id) + { + if (kernel_id) + { + *kernel_id = algorithm->kernel; + } + if (kernel_name) + { + *kernel_name = algorithm->name; + } + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->mutex_algs->unlock(this->mutex_algs); + return found; +} + +METHOD(kernel_interface_t, destroy, void, + private_kernel_interface_t *this) +{ + kernel_algorithm_t *algorithm; + + while (this->algorithms->remove_first(this->algorithms, + (void**)&algorithm) == SUCCESS) + { + free(algorithm->name); + free(algorithm); + } + this->algorithms->destroy(this->algorithms); + this->mutex_algs->destroy(this->mutex_algs); + DESTROY_IF(this->ipsec); + DESTROY_IF(this->net); + DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free); + this->reqids->destroy(this->reqids); + this->reqids_by_ts->destroy(this->reqids_by_ts); + this->listeners->destroy(this->listeners); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * Described in header-file + */ +kernel_interface_t *kernel_interface_create() +{ + private_kernel_interface_t *this; + char *ifaces; + + INIT(this, + .public = { + .get_features = _get_features, + .get_spi = _get_spi, + .get_cpi = _get_cpi, + .alloc_reqid = _alloc_reqid, + .release_reqid = _release_reqid, + .add_sa = _add_sa, + .update_sa = _update_sa, + .query_sa = _query_sa, + .del_sa = _del_sa, + .flush_sas = _flush_sas, + .add_policy = _add_policy, + .query_policy = _query_policy, + .del_policy = _del_policy, + .flush_policies = _flush_policies, + .get_source_addr = _get_source_addr, + .get_nexthop = _get_nexthop, + .get_interface = _get_interface, + .create_address_enumerator = _create_address_enumerator, + .add_ip = _add_ip, + .del_ip = _del_ip, + .add_route = _add_route, + .del_route = _del_route, + .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, + + .is_interface_usable = _is_interface_usable, + .all_interfaces_usable = _all_interfaces_usable, + .get_address_by_ts = _get_address_by_ts, + .add_ipsec_interface = _add_ipsec_interface, + .remove_ipsec_interface = _remove_ipsec_interface, + .add_net_interface = _add_net_interface, + .remove_net_interface = _remove_net_interface, + + .add_listener = _add_listener, + .remove_listener = _remove_listener, + .register_algorithm = _register_algorithm, + .lookup_algorithm = _lookup_algorithm, + .acquire = _acquire, + .expire = _expire, + .mapping = _mapping, + .migrate = _migrate, + .roam = _roam, + .tun = _tun, + .destroy = _destroy, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .listeners = linked_list_create(), + .mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT), + .algorithms = linked_list_create(), + .reqids = hashtable_create((hashtable_hash_t)hash_reqid, + (hashtable_equals_t)equals_reqid, 8), + .reqids_by_ts = hashtable_create((hashtable_hash_t)hash_reqid_by_ts, + (hashtable_equals_t)equals_reqid_by_ts, 8), + ); + + ifaces = lib->settings->get_str(lib->settings, + "%s.interfaces_use", NULL, lib->ns); + if (!ifaces) + { + this->ifaces_exclude = TRUE; + ifaces = lib->settings->get_str(lib->settings, + "%s.interfaces_ignore", NULL, lib->ns); + } + if (ifaces) + { + enumerator_t *enumerator; + char *iface; + + enumerator = enumerator_create_token(ifaces, ",", " "); + while (enumerator->enumerate(enumerator, &iface)) + { + if (!this->ifaces_filter) + { + this->ifaces_filter = linked_list_create(); + } + this->ifaces_filter->insert_last(this->ifaces_filter, + strdup(iface)); + } + enumerator->destroy(enumerator); + } + + return &this->public; +} diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h new file mode 100644 index 000000000..6793c6cc6 --- /dev/null +++ b/src/libcharon/kernel/kernel_interface.h @@ -0,0 +1,655 @@ +/* + * Copyright (C) 2006-2015 Tobias Brunner + * Copyright (C) 2006 Daniel Roethlisberger + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/* + * Copyright (c) 2012 Nanoteq Pty Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup kernel_interface kernel_interface + * @{ @ingroup kernel + */ + +#ifndef KERNEL_INTERFACE_H_ +#define KERNEL_INTERFACE_H_ + +typedef struct kernel_interface_t kernel_interface_t; +typedef enum kernel_feature_t kernel_feature_t; + +#include +#include + +#include +#include +#include + +/** + * Bitfield of optional features a kernel backend supports. + * + * This feature-set is for both, kernel_ipsec_t and kernel_net_t. Each + * backend returns a subset of these features. + */ +enum kernel_feature_t { + /** IPsec can process ESPv3 (RFC 4303) TFC padded packets */ + KERNEL_ESP_V3_TFC = (1<<0), + /** Networking requires an "exclude" route for IKE/ESP packets */ + KERNEL_REQUIRE_EXCLUDE_ROUTE = (1<<1), + /** IPsec implementation requires UDP encapsulation of ESP packets */ + KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2), + /** IPsec backend does not require a policy reinstall on SA updates */ + KERNEL_NO_POLICY_UPDATES = (1<<3), +}; + +/** + * Constructor function for ipsec kernel interface + */ +typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void); + +/** + * Constructor function for network kernel interface + */ +typedef kernel_net_t* (*kernel_net_constructor_t)(void); + +/** + * Manager and wrapper for different kernel interfaces. + * + * The kernel interface handles the communication with the kernel + * for SA and policy management and interface and IP address management. + */ +struct kernel_interface_t { + + /** + * Get the feature set supported by the net and ipsec kernel backends. + * + * @return ORed feature-set of backends + */ + kernel_feature_t (*get_features)(kernel_interface_t *this); + + /** + * Get a SPI from the kernel. + * + * @param src source address of SA + * @param dst destination address of SA + * @param protocol protocol for SA (ESP/AH) + * @param spi allocated spi + * @return SUCCESS if operation completed + */ + status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t *spi); + + /** + * Get a Compression Parameter Index (CPI) from the kernel. + * + * @param src source address of SA + * @param dst destination address of SA + * @param cpi allocated cpi + * @return SUCCESS if operation completed + */ + status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst, + u_int16_t *cpi); + + /** + * Allocate or confirm a reqid to use for a given SA pair. + * + * Each returned reqid by a successful call to alloc_reqid() must be + * released using release_reqid(). + * + * The reqid parameter is an in/out parameter. If it points to non-zero, + * the reqid is confirmed and registered for use. If it points to zero, + * a reqid is allocated for the given selectors, and returned to reqid. + * + * @param local_ts traffic selectors of local side for SA + * @param remote_ts traffic selectors of remote side for SA + * @param mark_in inbound mark on SA + * @param mark_out outbound mark on SA + * @param reqid allocated reqid + * @return SUCCESS if reqid allocated + */ + status_t (*alloc_reqid)(kernel_interface_t *this, + linked_list_t *local_ts, linked_list_t *remote_ts, + mark_t mark_in, mark_t mark_out, + u_int32_t *reqid); + + /** + * Release a previously allocated reqid. + * + * @param reqid reqid to release + * @param mark_in inbound mark on SA + * @param mark_out outbound mark on SA + * @return SUCCESS if reqid released + */ + status_t (*release_reqid)(kernel_interface_t *this, u_int32_t reqid, + mark_t mark_in, mark_t mark_out); + + /** + * Add an SA to the SAD. + * + * This function does install a single SA for a single protocol in one + * direction. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param reqid reqid for this SA + * @param mark optional mark for this SA + * @param tfc Traffic Flow Confidentiality padding for this SA + * @param lifetime lifetime_cfg_t for this SA + * @param enc_alg Algorithm to use for encryption (ESP only) + * @param enc_key key to use for encryption + * @param int_alg Algorithm to use for integrity protection + * @param int_key key to use for integrity protection + * @param mode mode of the SA (tunnel, transport) + * @param ipcomp IPComp transform to use + * @param cpi CPI for IPComp + * @param replay_window anti-replay window size + * @param initiator TRUE if initiator of the exchange creating this SA + * @param encap enable UDP encapsulation for NAT traversal + * @param esn TRUE to use Extended Sequence Numbers + * @param inbound TRUE if this is an inbound SA + * @param update TRUE if an SPI has already been allocated for SA + * @param src_ts list of source traffic selectors + * @param dst_ts list of destination traffic selectors + * @return SUCCESS if operation completed + */ + status_t (*add_sa) (kernel_interface_t *this, + host_t *src, host_t *dst, u_int32_t spi, + u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, + u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, + ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, + u_int32_t replay_window, bool initiator, bool encap, + bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts); + + /** + * Update the hosts on an installed SA. + * + * We cannot directly update the destination address as the kernel + * requires the spi, the protocol AND the destination address (and family) + * to identify SAs. Therefore if the destination address changed we + * create a new SA and delete the old one. + * + * @param spi SPI of the SA + * @param protocol protocol for this SA (ESP/AH) + * @param cpi CPI for IPComp, 0 if no IPComp is used + * @param src current source address + * @param dst current destination address + * @param new_src new source address + * @param new_dst new destination address + * @param encap current use of UDP encapsulation + * @param new_encap new use of UDP encapsulation + * @param mark optional mark for this SA + * @return SUCCESS if operation completed, NOT_SUPPORTED if + * the kernel interface can't update the SA + */ + status_t (*update_sa)(kernel_interface_t *this, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, + host_t *src, host_t *dst, + host_t *new_src, host_t *new_dst, + bool encap, bool new_encap, mark_t mark); + + /** + * Query the number of bytes processed by an SA from the SAD. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param mark optional mark for this SA + * @param[out] bytes the number of bytes processed by SA + * @param[out] packets number of packets processed by SA + * @param[out] time last (monotonic) time of SA use + * @return SUCCESS if operation completed + */ + status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, + u_int64_t *bytes, u_int64_t *packets, time_t *time); + + /** + * Delete a previously installed SA from the SAD. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param cpi CPI for IPComp or 0 + * @param mark optional mark for this SA + * @return SUCCESS if operation completed + */ + status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, + mark_t mark); + + /** + * Flush all SAs from the SAD. + * + * @return SUCCESS if operation completed + */ + status_t (*flush_sas) (kernel_interface_t *this); + + /** + * Add a policy to the SPD. + * + * @param src source address of SA + * @param dst dest address of SA + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param type type of policy, POLICY_(IPSEC|PASS|DROP) + * @param sa details about the SA(s) tied to this policy + * @param mark mark for this policy + * @param priority priority of this policy + * @return SUCCESS if operation completed + */ + status_t (*add_policy) (kernel_interface_t *this, + host_t *src, host_t *dst, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, + ipsec_sa_cfg_t *sa, mark_t mark, + policy_priority_t priority); + + /** + * Query the use time of a policy. + * + * The use time of a policy is the time the policy was used + * for the last time. + * + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param mark optional mark + * @param[out] use_time the (monotonic) time of this SA's last use + * @return SUCCESS if operation completed + */ + status_t (*query_policy) (kernel_interface_t *this, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, mark_t mark, + time_t *use_time); + + /** + * Remove a policy from the SPD. + * + * @param src source address of SA + * @param dst dest address of SA + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param type type of policy, POLICY_(IPSEC|PASS|DROP) + * @param sa details about the SA(s) tied to this policy + * @param mark mark for this policy + * @param priority priority of the policy + * @return SUCCESS if operation completed + */ + status_t (*del_policy) (kernel_interface_t *this, + host_t *src, host_t *dst, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, + ipsec_sa_cfg_t *sa, mark_t mark, + policy_priority_t priority); + + /** + * Flush all policies from the SPD. + * + * @return SUCCESS if operation completed + */ + status_t (*flush_policies) (kernel_interface_t *this); + + /** + * Get our outgoing source address for a destination. + * + * Does a route lookup to get the source address used to reach dest. + * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for the given source to dest. + * + * @param dest target destination address + * @param src source address to check, or NULL + * @return outgoing source address, NULL if unreachable + */ + host_t* (*get_source_addr)(kernel_interface_t *this, + host_t *dest, host_t *src); + + /** + * Get the next hop for a destination. + * + * Does a route lookup to get the next hop used to reach dest. + * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for the given source to dest. + * + * @param dest target destination address + * @param prefix prefix length if dest is a subnet, -1 for auto + * @param src source address to check, or NULL + * @return next hop address, NULL if unreachable + */ + host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest, + int prefix, host_t *src); + + /** + * Get the interface name of a local address. Interfaces that are down or + * ignored by config are not considered. + * + * @param host address to get interface name from + * @param name allocated interface name (optional) + * @return TRUE if interface found and usable + */ + bool (*get_interface)(kernel_interface_t *this, host_t *host, char **name); + + /** + * Creates an enumerator over all local addresses. + * + * This function blocks an internal cached address list until the + * enumerator gets destroyed. + * The hosts are read-only, do not modify of free. + * + * @param which a combination of address types to enumerate + * @return enumerator over host_t's + */ + enumerator_t *(*create_address_enumerator) (kernel_interface_t *this, + kernel_address_type_t which); + + /** + * Add a virtual IP to an interface. + * + * Virtual IPs are attached to an interface. If an IP is added multiple + * times, the IP is refcounted and not removed until del_ip() was called + * as many times as add_ip(). + * + * @param virtual_ip virtual ip address to assign + * @param prefix prefix length to install IP with, -1 for auto + * @param iface interface to install virtual IP on + * @return SUCCESS if operation completed + */ + status_t (*add_ip) (kernel_interface_t *this, host_t *virtual_ip, int prefix, + char *iface); + + /** + * Remove a virtual IP from an interface. + * + * The kernel interface uses refcounting, see add_ip(). + * + * @param virtual_ip virtual ip address to remove + * @param prefix prefix length of the IP to uninstall, -1 for auto + * @param wait TRUE to wait untily IP is gone + * @return SUCCESS if operation completed + */ + status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip, + int prefix, bool wait); + + /** + * Add a route. + * + * @param dst_net destination net + * @param prefixlen destination net prefix length + * @param gateway gateway for this route + * @param src_ip source ip of the route + * @param if_name name of the interface the route is bound to + * @return SUCCESS if operation completed + * ALREADY_DONE if the route already exists + */ + status_t (*add_route) (kernel_interface_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, + char *if_name); + + /** + * Delete a route. + * + * @param dst_net destination net + * @param prefixlen destination net prefix length + * @param gateway gateway for this route + * @param src_ip source ip of the route + * @param if_name name of the interface the route is bound to + * @return SUCCESS if operation completed + */ + status_t (*del_route) (kernel_interface_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, + char *if_name); + + /** + * Set up a bypass policy for a given socket. + * + * @param fd socket file descriptor to setup policy for + * @param family protocol family of the socket + * @return TRUE if policy set up successfully + */ + bool (*bypass_socket)(kernel_interface_t *this, int fd, int family); + + /** + * Enable decapsulation of ESP-in-UDP packets for the given port/socket. + * + * @param fd socket file descriptor + * @param family protocol family of the socket + * @param port the UDP port + * @return TRUE if UDP decapsulation was enabled successfully + */ + bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family, + u_int16_t port); + + + /** + * manager methods + */ + + /** + * Verifies that the given interface is usable and not excluded by + * configuration. + * + * @param iface interface name + * @return TRUE if usable + */ + bool (*is_interface_usable)(kernel_interface_t *this, const char *iface); + + /** + * Check if interfaces are excluded by config. + * + * @return TRUE if no interfaces are exclued by config + */ + bool (*all_interfaces_usable)(kernel_interface_t *this); + + /** + * Tries to find an IP address of a local interface that is included in the + * supplied traffic selector. + * + * @param ts traffic selector + * @param ip returned IP address (has to be destroyed) + * @param vip set to TRUE if returned address is a virtual IP + * @return SUCCESS if address found + */ + status_t (*get_address_by_ts)(kernel_interface_t *this, + traffic_selector_t *ts, host_t **ip, bool *vip); + + /** + * Register an ipsec kernel interface constructor on the manager. + * + * @param create constructor to register + * @return TRUE if the ipsec kernel interface was registered + * successfully, FALSE if an interface was already + * registered or the registration failed + */ + bool (*add_ipsec_interface)(kernel_interface_t *this, + kernel_ipsec_constructor_t create); + + /** + * Unregister an ipsec kernel interface constructor. + * + * @param create constructor to unregister + * @return TRUE if the ipsec kernel interface was unregistered + * successfully, FALSE otherwise + */ + bool (*remove_ipsec_interface)(kernel_interface_t *this, + kernel_ipsec_constructor_t create); + + /** + * Register a network kernel interface constructor on the manager. + * + * @param create constructor to register + * @return TRUE if the kernel net interface was registered + * successfully, FALSE if an interface was already + * registered or the registration failed + */ + bool (*add_net_interface)(kernel_interface_t *this, + kernel_net_constructor_t create); + + /** + * Unregister a network kernel interface constructor. + * + * @param create constructor to unregister + * @return TRUE if the kernel net interface was unregistered + * successfully, FALSE otherwise + */ + bool (*remove_net_interface)(kernel_interface_t *this, + kernel_net_constructor_t create); + + /** + * Add a listener to the kernel interface. + * + * @param listener listener to add + */ + void (*add_listener)(kernel_interface_t *this, + kernel_listener_t *listener); + + /** + * Remove a listener from the kernel interface. + * + * @param listener listener to remove + */ + void (*remove_listener)(kernel_interface_t *this, + kernel_listener_t *listener); + + /** + * Raise an acquire event. + * + * @param reqid reqid of the policy to acquire + * @param src_ts source traffic selector + * @param dst_ts destination traffic selector + */ + void (*acquire)(kernel_interface_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts); + + /** + * Raise an expire event. + * + * @param protocol protocol of the expired SA + * @param spi spi of the expired SA + * @param dst destination address of expired SA + * @param hard TRUE if it is a hard expire, FALSE otherwise + */ + void (*expire)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, bool hard); + + /** + * Raise a mapping event. + * + * @param protocol protocol of affected SA + * @param spi spi of the SA + * @param dst original destination address of SA + * @param remote new remote host + */ + void (*mapping)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, host_t *remote); + + /** + * Raise a migrate event. + * + * @param reqid reqid of the policy + * @param src_ts source traffic selector + * @param dst_ts destination traffic selector + * @param direction direction of the policy (in|out) + * @param local local host address to be used in the IKE_SA + * @param remote remote host address to be used in the IKE_SA + */ + void (*migrate)(kernel_interface_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, host_t *local, host_t *remote); + + /** + * Raise a roam event. + * + * @param address TRUE if address list, FALSE if routing changed + */ + void (*roam)(kernel_interface_t *this, bool address); + + /** + * Raise a tun event. + * + * @param tun TUN device + * @param created TRUE if created, FALSE if going to be destroyed + */ + void (*tun)(kernel_interface_t *this, tun_device_t *tun, bool created); + + /** + * Register a new algorithm with the kernel interface. + * + * @param alg_id the IKE id of the algorithm + * @param type the transform type of the algorithm + * @param kernel_id the kernel id of the algorithm + * @param kernel_name the kernel name of the algorithm + */ + void (*register_algorithm)(kernel_interface_t *this, u_int16_t alg_id, + transform_type_t type, u_int16_t kernel_id, + char *kernel_name); + + /** + * Return the kernel-specific id and/or name for an algorithms depending on + * the arguments specified. + * + * @param alg_id the IKE id of the algorithm + * @param type the transform type of the algorithm + * @param kernel_id the kernel id of the algorithm (optional) + * @param kernel_name the kernel name of the algorithm (optional) + * @return TRUE if algorithm was found + */ + bool (*lookup_algorithm)(kernel_interface_t *this, u_int16_t alg_id, + transform_type_t type, u_int16_t *kernel_id, + char **kernel_name); + + /** + * Destroys a kernel_interface_t object. + */ + void (*destroy) (kernel_interface_t *this); +}; + +/** + * Creates an object of type kernel_interface_t. + */ +kernel_interface_t *kernel_interface_create(void); + +#endif /** KERNEL_INTERFACE_H_ @}*/ diff --git a/src/libcharon/kernel/kernel_ipsec.c b/src/libcharon/kernel/kernel_ipsec.c new file mode 100644 index 000000000..0440f11bb --- /dev/null +++ b/src/libcharon/kernel/kernel_ipsec.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "kernel_ipsec.h" + +#include + +/** + * See header + */ +bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data) +{ + if (reg) + { + return charon->kernel->add_ipsec_interface(charon->kernel, + (kernel_ipsec_constructor_t)data); + } + else + { + return charon->kernel->remove_ipsec_interface(charon->kernel, + (kernel_ipsec_constructor_t)data); + } +} diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h new file mode 100644 index 000000000..31e06308e --- /dev/null +++ b/src/libcharon/kernel/kernel_ipsec.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2006-2015 Tobias Brunner + * Copyright (C) 2006 Daniel Roethlisberger + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup kernel_ipsec kernel_ipsec + * @{ @ingroup kernel + */ + +#ifndef KERNEL_IPSEC_H_ +#define KERNEL_IPSEC_H_ + +typedef struct kernel_ipsec_t kernel_ipsec_t; + +#include +#include +#include +#include +#include + +/** + * Interface to the ipsec subsystem of the kernel. + * + * The kernel ipsec interface handles the communication with the kernel + * for SA and policy management. It allows setup of these, and provides + * further the handling of kernel events. + * Policy information are cached in the interface. This is necessary to do + * reference counting. The Linux kernel does not allow the same policy + * installed twice, but we need this as CHILD_SA exist multiple times + * when rekeying. Thats why we do reference counting of policies. + */ +struct kernel_ipsec_t { + + /** + * Get the feature set supported by this kernel backend. + * + * @return ORed feature-set of backend + */ + kernel_feature_t (*get_features)(kernel_ipsec_t *this); + + /** + * Get a SPI from the kernel. + * + * @param src source address of SA + * @param dst destination address of SA + * @param protocol protocol for SA (ESP/AH) + * @param spi allocated spi + * @return SUCCESS if operation completed + */ + status_t (*get_spi)(kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t *spi); + + /** + * Get a Compression Parameter Index (CPI) from the kernel. + * + * @param src source address of SA + * @param dst destination address of SA + * @param cpi allocated cpi + * @return SUCCESS if operation completed + */ + status_t (*get_cpi)(kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int16_t *cpi); + + /** + * Add an SA to the SAD. + * + * This function does install a single SA for a single protocol in one + * direction. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param reqid unique ID for this SA + * @param mark mark for this SA + * @param tfc Traffic Flow Confidentiality padding for this SA + * @param lifetime lifetime_cfg_t for this SA + * @param enc_alg Algorithm to use for encryption (ESP only) + * @param enc_key key to use for encryption + * @param int_alg Algorithm to use for integrity protection + * @param int_key key to use for integrity protection + * @param mode mode of the SA (tunnel, transport) + * @param ipcomp IPComp transform to use + * @param cpi CPI for IPComp + * @param replay_window anti-replay window size + * @param initiator TRUE if initiator of the exchange creating this SA + * @param encap enable UDP encapsulation for NAT traversal + * @param esn TRUE to use Extended Sequence Numbers + * @param inbound TRUE if this is an inbound SA + * @param update TRUE if an SPI has already been allocated for SA + * @param src_ts list of source traffic selectors + * @param dst_ts list of destination traffic selectors + * @return SUCCESS if operation completed + */ + status_t (*add_sa) (kernel_ipsec_t *this, + host_t *src, host_t *dst, u_int32_t spi, + u_int8_t protocol, u_int32_t reqid, + mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime, + u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, + ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, + u_int32_t replay_window, bool initiator, bool encap, + bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts); + + /** + * Update the hosts on an installed SA. + * + * We cannot directly update the destination address as the kernel + * requires the spi, the protocol AND the destination address (and family) + * to identify SAs. Therefore if the destination address changed we + * create a new SA and delete the old one. + * + * @param spi SPI of the SA + * @param protocol protocol for this SA (ESP/AH) + * @param cpi CPI for IPComp, 0 if no IPComp is used + * @param src current source address + * @param dst current destination address + * @param new_src new source address + * @param new_dst new destination address + * @param encap current use of UDP encapsulation + * @param new_encap new use of UDP encapsulation + * @param mark optional mark for this SA + * @return SUCCESS if operation completed, NOT_SUPPORTED if + * the kernel interface can't update the SA + */ + status_t (*update_sa)(kernel_ipsec_t *this, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, + host_t *src, host_t *dst, + host_t *new_src, host_t *new_dst, + bool encap, bool new_encap, mark_t mark); + + /** + * Query the number of bytes processed by an SA from the SAD. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param mark optional mark for this SA + * @param[out] bytes the number of bytes processed by SA + * @param[out] packets number of packets processed by SA + * @param[out] time last (monotonic) time of SA use + * @return SUCCESS if operation completed + */ + status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, + u_int64_t *bytes, u_int64_t *packets, time_t *time); + + /** + * Delete a previusly installed SA from the SAD. + * + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param cpi CPI for IPComp or 0 + * @param mark optional mark for this SA + * @return SUCCESS if operation completed + */ + status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, + mark_t mark); + + /** + * Flush all SAs from the SAD. + * + * @return SUCCESS if operation completed + */ + status_t (*flush_sas) (kernel_ipsec_t *this); + + /** + * Add a policy to the SPD. + * + * @param src source address of SA + * @param dst dest address of SA + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param type type of policy, POLICY_(IPSEC|PASS|DROP) + * @param sa details about the SA(s) tied to this policy + * @param mark mark for this policy + * @param priority priority of this policy + * @return SUCCESS if operation completed + */ + status_t (*add_policy) (kernel_ipsec_t *this, + host_t *src, host_t *dst, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, + ipsec_sa_cfg_t *sa, mark_t mark, + policy_priority_t priority); + + /** + * Query the use time of a policy. + * + * The use time of a policy is the time the policy was used for the last + * time. It is not the system time, but a monotonic timestamp as returned + * by time_monotonic. + * + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param mark optional mark + * @param[out] use_time the monotonic timestamp of this SA's last use + * @return SUCCESS if operation completed + */ + status_t (*query_policy) (kernel_ipsec_t *this, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, mark_t mark, + time_t *use_time); + + /** + * Remove a policy from the SPD. + * + * @param src source address of SA + * @param dst dest address of SA + * @param src_ts traffic selector to match traffic source + * @param dst_ts traffic selector to match traffic dest + * @param direction direction of traffic, POLICY_(IN|OUT|FWD) + * @param type type of policy, POLICY_(IPSEC|PASS|DROP) + * @param sa details about the SA(s) tied to this policy + * @param mark mark for this policy + * @param priority priority of the policy + * @return SUCCESS if operation completed + */ + status_t (*del_policy) (kernel_ipsec_t *this, + host_t *src, host_t *dst, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, + ipsec_sa_cfg_t *sa, mark_t mark, + policy_priority_t priority); + + /** + * Flush all policies from the SPD. + * + * @return SUCCESS if operation completed + */ + status_t (*flush_policies) (kernel_ipsec_t *this); + + /** + * Install a bypass policy for the given socket. + * + * @param fd socket file descriptor to setup policy for + * @param family protocol family of the socket + * @return TRUE of policy set up successfully + */ + bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family); + + /** + * Enable decapsulation of ESP-in-UDP packets for the given port/socket. + * + * @param fd socket file descriptor + * @param family protocol family of the socket + * @param port the UDP port + * @return TRUE if UDP decapsulation was enabled successfully + */ + bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family, + u_int16_t port); + + /** + * Destroy the implementation. + */ + void (*destroy) (kernel_ipsec_t *this); +}; + +/** + * Helper function to (un-)register IPsec kernel interfaces from plugin features. + * + * This function is a plugin_feature_callback_t and can be used with the + * PLUGIN_CALLBACK macro to register an IPsec kernel interface constructor. + * + * @param plugin plugin registering the kernel interface + * @param feature associated plugin feature + * @param reg TRUE to register, FALSE to unregister + * @param data data passed to callback, an kernel_ipsec_constructor_t + */ +bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data); + +#endif /** KERNEL_IPSEC_H_ @}*/ diff --git a/src/libcharon/kernel/kernel_listener.h b/src/libcharon/kernel/kernel_listener.h new file mode 100644 index 000000000..6426fae2a --- /dev/null +++ b/src/libcharon/kernel/kernel_listener.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2010-2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup kernel_listener kernel_listener + * @{ @ingroup kernel + */ + +#ifndef KERNEL_LISTENER_H_ +#define KERNEL_LISTENER_H_ + +typedef struct kernel_listener_t kernel_listener_t; + +#include +#include +#include +#include + +/** + * Interface for components interested in kernel events. + * + * All hooks are optional. + */ +struct kernel_listener_t { + + /** + * Hook called if an acquire event for a policy is received. + * + * @param reqid reqid of the policy to acquire + * @param src_ts source traffic selector + * @param dst_ts destination traffic selector + * @return TRUE to remain registered, FALSE to unregister + */ + bool (*acquire)(kernel_listener_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts); + + /** + * Hook called if an exire event for an IPsec SA is received. + * + * @param protocol protocol of the expired SA + * @param spi spi of the expired SA + * @param dst destination address of expired SA + * @param hard TRUE if it is a hard expire, FALSE otherwise + * @return TRUE to remain registered, FALSE to unregister + */ + bool (*expire)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, bool hard); + + /** + * Hook called if the NAT mappings of an IPsec SA changed. + * + * @param protocol IPsec protocol of affected SA + * @param spi spi of the SA + * @param dst old destinatino address of SA + * @param remote new remote host + * @return TRUE to remain registered, FALSE to unregister + */ + bool (*mapping)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, host_t *remote); + + /** + * Hook called if a migrate event for a policy is received. + * + * @param reqid reqid of the policy + * @param src_ts source traffic selector + * @param dst_ts destination traffic selector + * @param direction direction of the policy (in|out) + * @param local local host address to be used in the IKE_SA + * @param remote remote host address to be used in the IKE_SA + * @return TRUE to remain registered, FALSE to unregister + */ + bool (*migrate)(kernel_listener_t *this, u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, host_t *local, host_t *remote); + + /** + * Hook called if changes in the networking layer occurred (interfaces + * up/down, routes added/deleted etc.). + * + * @param address TRUE if address list, FALSE if routing changed + * @return TRUE to remain registered, FALSE to unregister + */ + bool (*roam)(kernel_listener_t *this, bool address); + + /** + * Hook called after a TUN device was created for a virtual IP address, or + * before such a device gets destroyed. + * + * @param tun TUN device + * @param created TRUE if created, FALSE if going to be destroyed + */ + bool (*tun)(kernel_listener_t *this, tun_device_t *tun, bool created); +}; + +#endif /** KERNEL_LISTENER_H_ @}*/ diff --git a/src/libcharon/kernel/kernel_net.c b/src/libcharon/kernel/kernel_net.c new file mode 100644 index 000000000..f169cad14 --- /dev/null +++ b/src/libcharon/kernel/kernel_net.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "kernel_net.h" + +#include + +/** + * See header + */ +bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data) +{ + if (reg) + { + return charon->kernel->add_net_interface(charon->kernel, + (kernel_net_constructor_t)data); + } + else + { + return charon->kernel->remove_net_interface(charon->kernel, + (kernel_net_constructor_t)data); + } +} diff --git a/src/libcharon/kernel/kernel_net.h b/src/libcharon/kernel/kernel_net.h new file mode 100644 index 000000000..7fc644a7e --- /dev/null +++ b/src/libcharon/kernel/kernel_net.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2008-2012 Tobias Brunner + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup kernel_net kernel_net + * @{ @ingroup kernel + */ + +#ifndef KERNEL_NET_H_ +#define KERNEL_NET_H_ + +typedef struct kernel_net_t kernel_net_t; +typedef enum kernel_address_type_t kernel_address_type_t; + +#include +#include +#include +#include + +/** + * Type of addresses (e.g. when enumerating them) + */ +enum kernel_address_type_t { + /** normal addresses (on regular, up, non-ignored) interfaces */ + ADDR_TYPE_REGULAR = (1 << 0), + /** addresses on down interfaces */ + ADDR_TYPE_DOWN = (1 << 1), + /** addresses on ignored interfaces */ + ADDR_TYPE_IGNORED = (1 << 2), + /** addresses on loopback interfaces */ + ADDR_TYPE_LOOPBACK = (1 << 3), + /** virtual IP addresses */ + ADDR_TYPE_VIRTUAL = (1 << 4), + /** to enumerate all available addresses */ + ADDR_TYPE_ALL = (1 << 5) - 1, +}; + +/** + * Interface to the network subsystem of the kernel. + * + * The kernel network interface handles the communication with the kernel + * for interface and IP address management. + */ +struct kernel_net_t { + + /** + * Get the feature set supported by this kernel backend. + * + * @return ORed feature-set of backend + */ + kernel_feature_t (*get_features)(kernel_net_t *this); + + /** + * Get our outgoing source address for a destination. + * + * Does a route lookup to get the source address used to reach dest. + * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for the given source to dest. + * + * @param dest target destination address + * @param src source address to check, or NULL + * @return outgoing source address, NULL if unreachable + */ + host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest, host_t *src); + + /** + * Get the next hop for a destination. + * + * Does a route lookup to get the next hop used to reach dest. + * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for the given source to dest. + * + * @param dest target destination address + * @param prefix prefix length if dest is a subnet, -1 for auto + * @param src source address to check, or NULL + * @return next hop address, NULL if unreachable + */ + host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, int prefix, + host_t *src); + + /** + * Get the interface name of a local address. Interfaces that are down or + * ignored by config are not considered. + * + * @param host address to get interface name from + * @param name allocated interface name (optional) + * @return TRUE if interface found and usable + */ + bool (*get_interface) (kernel_net_t *this, host_t *host, char **name); + + /** + * Creates an enumerator over all local addresses. + * + * This function blocks an internal cached address list until the + * enumerator gets destroyed. + * The hosts are read-only, do not modify of free. + * + * @param which a combination of address types to enumerate + * @return enumerator over host_t's + */ + enumerator_t *(*create_address_enumerator) (kernel_net_t *this, + kernel_address_type_t which); + + /** + * Add a virtual IP to an interface. + * + * Virtual IPs are attached to an interface. If an IP is added multiple + * times, the IP is refcounted and not removed until del_ip() was called + * as many times as add_ip(). + * + * @param virtual_ip virtual ip address to assign + * @param prefix prefix length to install with IP address, -1 for auto + * @param iface interface to install virtual IP on + * @return SUCCESS if operation completed + */ + status_t (*add_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix, + char *iface); + + /** + * Remove a virtual IP from an interface. + * + * The kernel interface uses refcounting, see add_ip(). + * + * @param virtual_ip virtual ip address to remove + * @param prefix prefix length of the IP to uninstall, -1 for auto + * @param wait TRUE to wait until IP is gone + * @return SUCCESS if operation completed + */ + status_t (*del_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix, + bool wait); + + /** + * Add a route. + * + * @param dst_net destination net + * @param prefixlen destination net prefix length + * @param gateway gateway for this route + * @param src_ip source ip of the route + * @param if_name name of the interface the route is bound to + * @return SUCCESS if operation completed + * ALREADY_DONE if the route already exists + */ + status_t (*add_route) (kernel_net_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, + char *if_name); + + /** + * Delete a route. + * + * @param dst_net destination net + * @param prefixlen destination net prefix length + * @param gateway gateway for this route + * @param src_ip source ip of the route + * @param if_name name of the interface the route is bound to + * @return SUCCESS if operation completed + */ + status_t (*del_route) (kernel_net_t *this, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, host_t *src_ip, + char *if_name); + + /** + * Destroy the implementation. + */ + void (*destroy) (kernel_net_t *this); +}; + +/** + * Helper function to (un-)register net kernel interfaces from plugin features. + * + * This function is a plugin_feature_callback_t and can be used with the + * PLUGIN_CALLBACK macro to register an net kernel interface constructor. + * + * @param plugin plugin registering the kernel interface + * @param feature associated plugin feature + * @param reg TRUE to register, FALSE to unregister + * @param data data passed to callback, an kernel_net_constructor_t + */ +bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data); + +#endif /** KERNEL_NET_H_ @}*/ diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index a2f2016ff..ee357ca4d 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -20,7 +20,6 @@ #include "receiver.h" -#include #include #include #include @@ -451,9 +450,8 @@ static job_requeue_t receive_packets(private_receiver_t *this) dst = packet->get_destination(packet); src = packet->get_source(packet); - if (!hydra->kernel_interface->all_interfaces_usable(hydra->kernel_interface) - && !hydra->kernel_interface->get_interface(hydra->kernel_interface, - dst, NULL)) + if (!charon->kernel->all_interfaces_usable(charon->kernel) + && !charon->kernel->get_interface(charon->kernel, dst, NULL)) { DBG3(DBG_NET, "received packet from %#H to %#H on ignored interface", src, dst); diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am index 33ee60d86..ddb2706c8 100644 --- a/src/libcharon/plugins/addrblock/Makefile.am +++ b/src/libcharon/plugins/addrblock/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index 0554465b9..b4ae6fa3e 100644 --- a/src/libcharon/plugins/addrblock/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am index 1a0d6e6f2..e606a832c 100644 --- a/src/libcharon/plugins/android_dns/Makefile.am +++ b/src/libcharon/plugins/android_dns/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in index 58cf97b6e..d90149827 100644 --- a/src/libcharon/plugins/android_dns/Makefile.in +++ b/src/libcharon/plugins/android_dns/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am index 79c61b51e..9f82f6e60 100644 --- a/src/libcharon/plugins/android_log/Makefile.am +++ b/src/libcharon/plugins/android_log/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in index 8ce92e577..64fecd9e3 100644 --- a/src/libcharon/plugins/android_log/Makefile.in +++ b/src/libcharon/plugins/android_log/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/attr/Makefile.am b/src/libcharon/plugins/attr/Makefile.am index 6bc7e77d8..ecbb76d1a 100644 --- a/src/libcharon/plugins/attr/Makefile.am +++ b/src/libcharon/plugins/attr/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/attr/Makefile.in b/src/libcharon/plugins/attr/Makefile.in index 486b3c0b0..acb7d07c0 100644 --- a/src/libcharon/plugins/attr/Makefile.in +++ b/src/libcharon/plugins/attr/Makefile.in @@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -428,7 +430,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c index cac0ae4bf..1de571c3f 100644 --- a/src/libcharon/plugins/attr/attr_provider.c +++ b/src/libcharon/plugins/attr/attr_provider.c @@ -54,6 +54,8 @@ struct attribute_entry_t { configuration_attribute_type_t type; /** attribute value */ chunk_t value; + /** associated IKE version */ + ike_version_t ike; }; /** @@ -65,27 +67,52 @@ static void attribute_destroy(attribute_entry_t *this) free(this); } +/** + * Data for attribute enumerator + */ +typedef struct { + rwlock_t *lock; + ike_version_t ike; +} enumerator_data_t; + /** * convert enumerator value from attribute_entry */ -static bool attr_enum_filter(void *null, attribute_entry_t **in, +static bool attr_enum_filter(enumerator_data_t *data, attribute_entry_t **in, configuration_attribute_type_t *type, void* none, chunk_t *value) { - *type = (*in)->type; - *value = (*in)->value; - return TRUE; + if ((*in)->ike == IKE_ANY || (*in)->ike == data->ike) + { + *type = (*in)->type; + *value = (*in)->value; + return TRUE; + } + return FALSE; +} + +CALLBACK(attr_enum_destroy, void, + enumerator_data_t *data) +{ + data->lock->unlock(data->lock); + free(data); } METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_attr_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, linked_list_t *vips) { + enumerator_data_t *data; + if (vips->get_count(vips)) { + INIT(data, + .lock = this->lock, + .ike = ike_sa->get_version(ike_sa), + ); this->lock->read_lock(this->lock); return enumerator_create_filter( this->attributes->create_enumerator(this->attributes), - (void*)attr_enum_filter, this->lock, (void*)this->lock->unlock); + (void*)attr_enum_filter, data, attr_enum_destroy); } return enumerator_create_empty(); } @@ -116,8 +143,6 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr, host = host_create_from_string(str, 0); if (host) { - entry = malloc_thing(attribute_entry_t); - if (host->get_family(host) == AF_INET6) { switch (type) @@ -132,8 +157,11 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr, break; } } - entry->type = type; - entry->value = chunk_clone(host->get_address(host)); + INIT(entry, + .type = type, + .value = chunk_clone(host->get_address(host)), + .ike = IKE_ANY, + ); host->destroy(host); DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B", configuration_attribute_type_names, entry->type, &entry->value); @@ -149,18 +177,20 @@ typedef struct { char *name; configuration_attribute_type_t v4; configuration_attribute_type_t v6; + ike_version_t ike; } attribute_type_key_t; static attribute_type_key_t keys[] = { - {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS}, - {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS}, - {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS}, - {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP}, - {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK}, - {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER}, - {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET}, - {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE}, - {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN}, + {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS, IKE_ANY}, + {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS, IKE_ANY}, + {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS, IKE_ANY}, + {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP, IKE_ANY}, + {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK, IKE_ANY}, + {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, IKE_ANY}, + {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET, IKE_ANY}, + {"p-cscf", P_CSCF_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, IKEV2}, + {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE, IKEV1}, + {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN, IKEV1}, }; /** @@ -275,6 +305,7 @@ static void load_entries(private_attr_provider_t *this) INIT(entry, .type = type, .value = data, + .ike = mapped ? mapped->ike : IKE_ANY, ); DBG2(DBG_CFG, "loaded attribute %N: %#B", configuration_attribute_type_names, entry->type, &entry->value); diff --git a/src/libcharon/plugins/attr_sql/Makefile.am b/src/libcharon/plugins/attr_sql/Makefile.am index 366c902f7..e65ef36a1 100644 --- a/src/libcharon/plugins/attr_sql/Makefile.am +++ b/src/libcharon/plugins/attr_sql/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/attr_sql/Makefile.in b/src/libcharon/plugins/attr_sql/Makefile.in index 8f1b3c0ff..8ee9f3f92 100644 --- a/src/libcharon/plugins/attr_sql/Makefile.in +++ b/src/libcharon/plugins/attr_sql/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am index b8c241dfb..d2d38efea 100644 --- a/src/libcharon/plugins/certexpire/Makefile.am +++ b/src/libcharon/plugins/certexpire/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in index f946d73c1..be19d615e 100644 --- a/src/libcharon/plugins/certexpire/Makefile.in +++ b/src/libcharon/plugins/certexpire/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/connmark/Makefile.am b/src/libcharon/plugins/connmark/Makefile.am index cc4d0ec8d..561efa0af 100644 --- a/src/libcharon/plugins/connmark/Makefile.am +++ b/src/libcharon/plugins/connmark/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/connmark/Makefile.in b/src/libcharon/plugins/connmark/Makefile.in index 65f53fde9..eaf4f1ec9 100644 --- a/src/libcharon/plugins/connmark/Makefile.in +++ b/src/libcharon/plugins/connmark/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c index 23df690e8..607316f7b 100644 --- a/src/libcharon/plugins/connmark/connmark_listener.c +++ b/src/libcharon/plugins/connmark/connmark_listener.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * @@ -25,6 +28,14 @@ #include #include +/** + * Add a struct at the current position in the buffer + */ +#define ADD_STRUCT(pos, st, ...) ({\ + typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\ + *(st*)_cur = (st){ __VA_ARGS__ };\ + (st*)_cur;\ +}) typedef struct private_connmark_listener_t private_connmark_listener_t; @@ -90,7 +101,10 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain, } else { - if (!iptc_delete_entry(chain, e, "", ipth)) + u_char matchmask[e->next_offset]; + + memset(matchmask, 255, sizeof(matchmask)); + if (!iptc_delete_entry(chain, e, matchmask, ipth)) { DBG1(DBG_CFG, "deleting %s rule failed: %s", chain, iptc_strerror(errno)); @@ -108,54 +122,54 @@ static bool manage_pre_esp_in_udp(private_connmark_listener_t *this, u_int mark, u_int32_t spi, host_t *dst, host_t *src) { - struct { - struct ipt_entry e; - struct ipt_entry_match m; - struct xt_udp udp; - struct ipt_entry_target t; - struct xt_mark_tginfo2 tm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + - sizeof(ipt.udp)), - .next_offset = sizeof(ipt), - .ip = { - .proto = IPPROTO_UDP, - }, + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_udp)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_mark_tginfo2)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + .ip = { + .proto = IPPROTO_UDP, }, - .m = { - .u = { - .user = { - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)), - .name = "udp", - }, + ); + if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) || + !host2in(src, &e->ip.src, &e->ip.smsk)) + { + return FALSE; + } + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "udp", }, }, - .udp = { - .spts = { src->get_port(src), src->get_port(src) }, - .dpts = { dst->get_port(dst), dst->get_port(dst) }, - }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), - .name = "MARK", - .revision = 2, - }, + ); + ADD_STRUCT(pos, struct xt_udp, + .spts = { src->get_port(src), src->get_port(src) }, + .dpts = { dst->get_port(dst), dst->get_port(dst) }, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "MARK", + .revision = 2, }, }, - .tm = { - .mark = mark, - .mask = ~0, - }, - }; - - if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) - { - return FALSE; - } - return manage_rule(ipth, "PREROUTING", add, &ipt.e); + ); + ADD_STRUCT(pos, struct xt_mark_tginfo2, + .mark = mark, + .mask = ~0, + ); + return manage_rule(ipth, "PREROUTING", add, e); } /** @@ -166,53 +180,53 @@ static bool manage_pre_esp(private_connmark_listener_t *this, u_int mark, u_int32_t spi, host_t *dst, host_t *src) { - struct { - struct ipt_entry e; - struct ipt_entry_match m; - struct xt_esp esp; - struct ipt_entry_target t; - struct xt_mark_tginfo2 tm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + - sizeof(ipt.esp)), - .next_offset = sizeof(ipt), - .ip = { - .proto = IPPROTO_ESP, - }, + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_esp)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_mark_tginfo2)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + .ip = { + .proto = IPPROTO_ESP, }, - .m = { - .u = { - .user = { - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)), - .name = "esp", - }, + ); + if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) || + !host2in(src, &e->ip.src, &e->ip.smsk)) + { + return FALSE; + } + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "esp", }, }, - .esp = { - .spis = { htonl(spi), htonl(spi) }, - }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), - .name = "MARK", - .revision = 2, - }, + ); + ADD_STRUCT(pos, struct xt_esp, + .spis = { htonl(spi), htonl(spi) }, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "MARK", + .revision = 2, }, }, - .tm = { - .mark = mark, - .mask = ~0, - }, - }; - - if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) - { - return FALSE; - } - return manage_rule(ipth, "PREROUTING", add, &ipt.e); + ); + ADD_STRUCT(pos, struct xt_mark_tginfo2, + .mark = mark, + .mask = ~0, + ); + return manage_rule(ipth, "PREROUTING", add, e); } /** @@ -238,99 +252,115 @@ static bool manage_in(private_connmark_listener_t *this, u_int mark, u_int32_t spi, traffic_selector_t *dst, traffic_selector_t *src) { - struct { - struct ipt_entry e; - struct ipt_entry_match m; - struct xt_policy_info p; - struct ipt_entry_target t; - struct xt_connmark_tginfo1 cm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + - sizeof(ipt.p)), - .next_offset = sizeof(ipt), - }, - .m = { - .u = { - .user = { - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)), - .name = "policy", - }, + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_policy_info)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_connmark_tginfo1)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + ); + if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) || + !ts2in(src, &e->ip.src, &e->ip.smsk)) + { + return FALSE; + } + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "policy", }, }, - .p = { - .pol = { - { - .spi = spi, - .match.spi = 1, - }, + ); + ADD_STRUCT(pos, struct xt_policy_info, + .pol = { + { + .spi = spi, + .match.spi = 1, }, - .len = 1, - .flags = XT_POLICY_MATCH_IN, }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)), - .name = "CONNMARK", - .revision = 1, - }, + .len = 1, + .flags = XT_POLICY_MATCH_IN, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "CONNMARK", + .revision = 1, }, }, - .cm = { - .ctmark = mark, - .ctmask = ~0, - .nfmask = ~0, - .mode = XT_CONNMARK_SET, - }, - }; - - if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) - { - return FALSE; - } - return manage_rule(ipth, "INPUT", add, &ipt.e); + ); + ADD_STRUCT(pos, struct xt_connmark_tginfo1, + .ctmark = mark, + .ctmask = ~0, + .nfmask = ~0, + .mode = XT_CONNMARK_SET, + ); + return manage_rule(ipth, "INPUT", add, e); } /** - * Add outbund rule restoring CONNMARK on matching traffic + * Add outbund rule restoring CONNMARK on matching traffic unless the packet + * already has a mark set */ static bool manage_out(private_connmark_listener_t *this, struct iptc_handle *ipth, bool add, traffic_selector_t *dst, traffic_selector_t *src) { - struct { - struct ipt_entry e; - struct ipt_entry_target t; - struct xt_connmark_tginfo1 cm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e)), - .next_offset = sizeof(ipt), - }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)), - .name = "CONNMARK", - .revision = 1, - }, - }, - }, - .cm = { - .ctmask = ~0, - .nfmask = ~0, - .mode = XT_CONNMARK_RESTORE, - }, - }; - - if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_mark_mtinfo1)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_connmark_tginfo1)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + ); + if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) || + !ts2in(src, &e->ip.src, &e->ip.smsk)) { return FALSE; } - return manage_rule(ipth, "OUTPUT", add, &ipt.e); + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "mark", + .revision = 1, + }, + }, + ); + ADD_STRUCT(pos, struct xt_mark_mtinfo1, + .mask = ~0, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "CONNMARK", + .revision = 1, + }, + }, + ); + ADD_STRUCT(pos, struct xt_connmark_tginfo1, + .ctmask = ~0, + .nfmask = ~0, + .mode = XT_CONNMARK_RESTORE, + ); + return manage_rule(ipth, "OUTPUT", add, e); } /** diff --git a/src/libcharon/plugins/coupling/Makefile.am b/src/libcharon/plugins/coupling/Makefile.am index badc7b7b2..62695aabe 100644 --- a/src/libcharon/plugins/coupling/Makefile.am +++ b/src/libcharon/plugins/coupling/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in index dff80c37f..44598c3ea 100644 --- a/src/libcharon/plugins/coupling/Makefile.in +++ b/src/libcharon/plugins/coupling/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/dhcp/Makefile.am b/src/libcharon/plugins/dhcp/Makefile.am index 3c09db016..9ae68be35 100644 --- a/src/libcharon/plugins/dhcp/Makefile.am +++ b/src/libcharon/plugins/dhcp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index 1e84f04e2..3d39fda29 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c index b8c1b4059..0fd1d33fd 100644 --- a/src/libcharon/plugins/dhcp/dhcp_socket.c +++ b/src/libcharon/plugins/dhcp/dhcp_socket.c @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -209,8 +208,7 @@ static int prepare_dhcp(private_dhcp_socket_t *this, else { /* act as relay agent */ - src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface, - this->dst, NULL); + src = charon->kernel->get_source_addr(charon->kernel, this->dst, NULL); if (src) { memcpy(&dhcp->gateway_address, src->get_address(src).ptr, diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am index 145562522..8181bfc9e 100644 --- a/src/libcharon/plugins/dnscert/Makefile.am +++ b/src/libcharon/plugins/dnscert/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in index ed873b316..04fc31a3a 100644 --- a/src/libcharon/plugins/dnscert/Makefile.in +++ b/src/libcharon/plugins/dnscert/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/duplicheck/Makefile.am b/src/libcharon/plugins/duplicheck/Makefile.am index 338a114fe..32b850ccb 100644 --- a/src/libcharon/plugins/duplicheck/Makefile.am +++ b/src/libcharon/plugins/duplicheck/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in index 41862cb2a..da4534c21 100644 --- a/src/libcharon/plugins/duplicheck/Makefile.in +++ b/src/libcharon/plugins/duplicheck/Makefile.in @@ -423,6 +423,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -438,7 +440,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/duplicheck/duplicheck.c b/src/libcharon/plugins/duplicheck/duplicheck.c index 508e8e386..7c4cd5ce1 100644 --- a/src/libcharon/plugins/duplicheck/duplicheck.c +++ b/src/libcharon/plugins/duplicheck/duplicheck.c @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include "duplicheck_msg.h" diff --git a/src/libcharon/plugins/eap_aka/Makefile.am b/src/libcharon/plugins/eap_aka/Makefile.am index 75e8eafb2..5d7ab8485 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.am +++ b/src/libcharon/plugins/eap_aka/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index dacddfb87..b5ffd8c24 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am index ec145a39e..d68bfc4c4 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index 3c26b8511..e0ad6fe2e 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.am b/src/libcharon/plugins/eap_dynamic/Makefile.am index 58b827a78..fd08846a9 100644 --- a/src/libcharon/plugins/eap_dynamic/Makefile.am +++ b/src/libcharon/plugins/eap_dynamic/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in index 402c7cadc..821f6de6c 100644 --- a/src/libcharon/plugins/eap_dynamic/Makefile.in +++ b/src/libcharon/plugins/eap_dynamic/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am index c3a12ba3e..a7d1f6275 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.am +++ b/src/libcharon/plugins/eap_gtc/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 2279b2514..cfd7c4e24 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_identity/Makefile.am b/src/libcharon/plugins/eap_identity/Makefile.am index 6c5b43f00..4c44962bd 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.am +++ b/src/libcharon/plugins/eap_identity/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index 30d2c88d1..1c544f360 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_md5/Makefile.am b/src/libcharon/plugins/eap_md5/Makefile.am index 16aa1919b..b27e8cc54 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.am +++ b/src/libcharon/plugins/eap_md5/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index 14616c214..e967262b6 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.am b/src/libcharon/plugins/eap_mschapv2/Makefile.am index 4276a082d..ded9bbe3f 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.am +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index 78dfd29e3..d96343a5c 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/eap_peap/Makefile.am b/src/libcharon/plugins/eap_peap/Makefile.am index 8960b84bd..ef226169d 100644 --- a/src/libcharon/plugins/eap_peap/Makefile.am +++ b/src/libcharon/plugins/eap_peap/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in index 2f0d65d6d..0f920fef8 100644 --- a/src/libcharon/plugins/eap_peap/Makefile.in +++ b/src/libcharon/plugins/eap_peap/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index bc7a7765d..78cf99184 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 47534372b..881a5b7e3 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/eap_sim/Makefile.am b/src/libcharon/plugins/eap_sim/Makefile.am index f68138579..8d93077e2 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.am +++ b/src/libcharon/plugins/eap_sim/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in index 251eeeeba..aaa24bb17 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am index c38e55e2c..5c5694c18 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.am +++ b/src/libcharon/plugins/eap_sim_file/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka \ -DIPSEC_CONFDIR=\"${sysconfdir}\" diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index bffcbc0df..6e61f99de 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka \ -DIPSEC_CONFDIR=\"${sysconfdir}\" diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am index 22922049d..5e235e7ea 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in index 78682ce37..e821e3ee2 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in @@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -434,7 +436,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am index f40efbd6f..c0d7b914c 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index 2a6be5fd9..b883f0abd 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -434,7 +436,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am index 0fb622220..9e55bb188 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index de504d4cd..5417f9639 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am index b7d6fd43e..f4c478dba 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka \ -DIPSEC_CONFDIR=\"${sysconfdir}\" diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in index de3508a07..c858e467c 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libsimaka \ -DIPSEC_CONFDIR=\"${sysconfdir}\" diff --git a/src/libcharon/plugins/eap_tls/Makefile.am b/src/libcharon/plugins/eap_tls/Makefile.am index 825beb841..551ecb380 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.am +++ b/src/libcharon/plugins/eap_tls/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in index d4219b876..c953d0e9c 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.in +++ b/src/libcharon/plugins/eap_tls/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls diff --git a/src/libcharon/plugins/eap_tnc/Makefile.am b/src/libcharon/plugins/eap_tnc/Makefile.am index 6fc78bc9a..186ae45e2 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.am +++ b/src/libcharon/plugins/eap_tnc/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libtncif \ diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in index 6c34ed098..2f197ed33 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.in +++ b/src/libcharon/plugins/eap_tnc/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libtncif \ diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index 350001bb4..621caffee 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -328,7 +328,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type, is_server, server, peer, server_ip, peer_ip, (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0, - is_server ? enforce_recommendation : NULL); + enforce_recommendation); if (!tnccs) { DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol); diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am index 3a7a8cda3..3db20e348 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.am +++ b/src/libcharon/plugins/eap_ttls/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in index 0babf1766..b563acdda 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.in +++ b/src/libcharon/plugins/eap_ttls/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/error_notify/Makefile.am b/src/libcharon/plugins/error_notify/Makefile.am index 1c64bd2cc..766bb4c51 100644 --- a/src/libcharon/plugins/error_notify/Makefile.am +++ b/src/libcharon/plugins/error_notify/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in index 0a07aa7a3..03dfe3d60 100644 --- a/src/libcharon/plugins/error_notify/Makefile.in +++ b/src/libcharon/plugins/error_notify/Makefile.in @@ -424,6 +424,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -439,7 +441,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/ext_auth/Makefile.am b/src/libcharon/plugins/ext_auth/Makefile.am index d51ea8881..7028819aa 100644 --- a/src/libcharon/plugins/ext_auth/Makefile.am +++ b/src/libcharon/plugins/ext_auth/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in index d23e680aa..fce2e8e63 100644 --- a/src/libcharon/plugins/ext_auth/Makefile.in +++ b/src/libcharon/plugins/ext_auth/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/farp/Makefile.am b/src/libcharon/plugins/farp/Makefile.am index 0d862b0a9..6d96f3abb 100644 --- a/src/libcharon/plugins/farp/Makefile.am +++ b/src/libcharon/plugins/farp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index 318400fc9..2afc5ad76 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/forecast/Makefile.am b/src/libcharon/plugins/forecast/Makefile.am index ce573135d..77535294e 100644 --- a/src/libcharon/plugins/forecast/Makefile.am +++ b/src/libcharon/plugins/forecast/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/forecast/Makefile.in b/src/libcharon/plugins/forecast/Makefile.in index 7b190ca25..4f2a407b4 100644 --- a/src/libcharon/plugins/forecast/Makefile.in +++ b/src/libcharon/plugins/forecast/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/forecast/forecast_forwarder.c b/src/libcharon/plugins/forecast/forecast_forwarder.c index 07a3d4953..40aaa7f25 100644 --- a/src/libcharon/plugins/forecast/forecast_forwarder.c +++ b/src/libcharon/plugins/forecast/forecast_forwarder.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -428,8 +427,7 @@ METHOD(forecast_forwarder_t, destroy, void, lib->watcher->remove(lib->watcher, this->kernel.pkt); close(this->kernel.pkt); } - hydra->kernel_interface->remove_listener(hydra->kernel_interface, - &this->kernel.listener); + charon->kernel->remove_listener(charon->kernel, &this->kernel.listener); free(this); } @@ -486,8 +484,8 @@ forecast_forwarder_t *forecast_forwarder_create(forecast_listener_t *listener) setup_interface(&this->kernel); - hydra->kernel_interface->add_listener(hydra->kernel_interface, - &this->kernel.listener); + charon->kernel->add_listener(charon->kernel, + &this->kernel.listener); lib->watcher->add(lib->watcher, this->kernel.pkt, WATCHER_READ, (watcher_cb_t)receive_casts, this); diff --git a/src/libcharon/plugins/forecast/forecast_listener.c b/src/libcharon/plugins/forecast/forecast_listener.c index 63a8cb15b..8f7f2600c 100644 --- a/src/libcharon/plugins/forecast/forecast_listener.c +++ b/src/libcharon/plugins/forecast/forecast_listener.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010-2014 Martin Willi * Copyright (C) 2010-2014 revosec AG * @@ -25,6 +28,15 @@ #include #include +/** + * Add a struct at the current position in the buffer + */ +#define ADD_STRUCT(pos, st, ...) ({\ + typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\ + *(st*)_cur = (st){ __VA_ARGS__ };\ + (st*)_cur;\ +}) + typedef struct private_forecast_listener_t private_forecast_listener_t; /** @@ -148,7 +160,10 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain, } else { - if (!iptc_delete_entry(chain, e, "", ipth)) + u_char matchmask[e->next_offset]; + + memset(matchmask, 255, sizeof(matchmask)); + if (!iptc_delete_entry(chain, e, matchmask, ipth)) { DBG1(DBG_CFG, "deleting %s rule failed: %s", chain, iptc_strerror(errno)); @@ -164,60 +179,60 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain, static bool manage_pre_esp_in_udp(struct iptc_handle *ipth, entry_t *entry, bool add) { - struct { - struct ipt_entry e; - struct ipt_entry_match m; - struct xt_udp udp; - struct ipt_entry_target t; - struct xt_mark_tginfo2 tm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + - sizeof(ipt.udp)), - .next_offset = sizeof(ipt), - .ip = { - .proto = IPPROTO_UDP, - }, + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_udp)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_mark_tginfo2)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + .ip = { + .proto = IPPROTO_UDP, }, - .m = { - .u = { - .user = { - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)), - .name = "udp", - }, + ); + if (!host2in(entry->lhost, &e->ip.dst, &e->ip.dmsk) || + !host2in(entry->rhost, &e->ip.src, &e->ip.smsk)) + { + return FALSE; + } + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "udp", }, }, - .udp = { - .spts = { - entry->rhost->get_port(entry->rhost), - entry->rhost->get_port(entry->lhost) - }, - .dpts = { - entry->lhost->get_port(entry->lhost), - entry->lhost->get_port(entry->lhost) - }, + ); + ADD_STRUCT(pos, struct xt_udp, + .spts = { + entry->rhost->get_port(entry->rhost), + entry->rhost->get_port(entry->lhost) }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), - .name = "MARK", - .revision = 2, - }, - }, + .dpts = { + entry->lhost->get_port(entry->lhost), + entry->lhost->get_port(entry->lhost) }, - .tm = { - .mark = entry->mark, - .mask = ~0, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "MARK", + .revision = 2, + }, }, - }; - - if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk)) - { - return FALSE; - } - return manage_rule(ipth, "PREROUTING", add, &ipt.e); + ); + ADD_STRUCT(pos, struct xt_mark_tginfo2, + .mark = entry->mark, + .mask = ~0, + ); + return manage_rule(ipth, "PREROUTING", add, e); } /** @@ -225,53 +240,53 @@ static bool manage_pre_esp_in_udp(struct iptc_handle *ipth, */ static bool manage_pre_esp(struct iptc_handle *ipth, entry_t *entry, bool add) { - struct { - struct ipt_entry e; - struct ipt_entry_match m; - struct xt_esp esp; - struct ipt_entry_target t; - struct xt_mark_tginfo2 tm; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + - sizeof(ipt.esp)), - .next_offset = sizeof(ipt), - .ip = { - .proto = IPPROTO_ESP, - }, + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_esp)); + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size; + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_mark_tginfo2)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + .ip = { + .proto = IPPROTO_ESP, }, - .m = { - .u = { - .user = { - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)), - .name = "esp", - }, + ); + if (!host2in(entry->lhost, &e->ip.dst, &e->ip.dmsk) || + !host2in(entry->rhost, &e->ip.src, &e->ip.smsk)) + { + return FALSE; + } + ADD_STRUCT(pos, struct ipt_entry_match, + .u = { + .user = { + .match_size = match_size, + .name = "esp", }, }, - .esp = { - .spis = { htonl(entry->spi), htonl(entry->spi) }, - }, - .t = { - .u = { - .user = { - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), - .name = "MARK", - .revision = 2, - }, + ); + ADD_STRUCT(pos, struct xt_esp, + .spis = { htonl(entry->spi), htonl(entry->spi) }, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "MARK", + .revision = 2, }, }, - .tm = { - .mark = entry->mark, - .mask = ~0, - }, - }; - - if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || - !host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk)) - { - return FALSE; - } - return manage_rule(ipth, "PREROUTING", add, &ipt.e); + ); + ADD_STRUCT(pos, struct xt_mark_tginfo2, + .mark = entry->mark, + .mask = ~0, + ); + return manage_rule(ipth, "PREROUTING", add, e); } /** @@ -291,45 +306,52 @@ static bool manage_pre(struct iptc_handle *ipth, entry_t *entry, bool add) */ static bool manage_out(struct iptc_handle *ipth, entry_t *entry, bool add) { - struct { - struct ipt_entry e; - struct ipt_entry_target t; - struct xt_mark_tginfo2 m; - } ipt = { - .e = { - .target_offset = XT_ALIGN(sizeof(ipt.e)), - .next_offset = sizeof(ipt), - }, - .t = { - .u.user.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.m)), - .u.user.name = "MARK", - .u.user.revision = 2, - }, - .m = { - .mark = entry->mark, - .mask = ~0, + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)); + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_mark_tginfo2)); + u_int16_t entry_size = target_offset + target_size; + u_char ipt[entry_size], *pos = ipt; + struct ipt_entry *e; + + memset(ipt, 0, sizeof(ipt)); + e = ADD_STRUCT(pos, struct ipt_entry, + .target_offset = target_offset, + .next_offset = entry_size, + ); + ADD_STRUCT(pos, struct ipt_entry_target, + .u = { + .user = { + .target_size = target_size, + .name = "MARK", + .revision = 2, + }, }, - }; + ); + ADD_STRUCT(pos, struct xt_mark_tginfo2, + .mark = entry->mark, + .mask = ~0, + ); + enumerator_t *enumerator; traffic_selector_t *ts; enumerator = array_create_enumerator(entry->rts); while (enumerator->enumerate(enumerator, &ts)) { - if (!ts2in(ts, &ipt.e.ip.dst, &ipt.e.ip.dmsk)) + if (!ts2in(ts, &e->ip.dst, &e->ip.dmsk)) { continue; } - if (ipt.e.ip.dst.s_addr == 0xffffffff || - ipt.e.ip.dst.s_addr == entry->broadcast || - memeq(&ipt.e.ip.dst.s_addr, "\xe0", 1)) + if (e->ip.dst.s_addr == 0xffffffff || + e->ip.dst.s_addr == entry->broadcast || + memeq(&e->ip.dst.s_addr, "\xe0", 1)) { /* skip broadcast/multicast selectors, they are shared and the mark * is set by the socket we use for reinjection */ continue; } - if (!manage_rule(ipth, "PREROUTING", add, &ipt.e) || - !manage_rule(ipth, "OUTPUT", add, &ipt.e)) + if (!manage_rule(ipth, "PREROUTING", add, e) || + !manage_rule(ipth, "OUTPUT", add, e)) { enumerator->destroy(enumerator); return FALSE; diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am index 50d342389..d501834d7 100644 --- a/src/libcharon/plugins/ha/Makefile.am +++ b/src/libcharon/plugins/ha/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index de74f88cc..677c36afe 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index dbb6adc8f..7dafb1693 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -91,6 +91,10 @@ METHOD(listener_t, child_keys, bool, { m->add_attribute(m, HA_ALG_INTEG, alg); } + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL)) + { + m->add_attribute(m, HA_ALG_DH, alg); + } if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, &alg, NULL)) { m->add_attribute(m, HA_ESN, alg); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 07ef607c6..ce90f5bfe 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -132,6 +132,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message ike_sa_t *ike_sa = NULL, *old_sa = NULL; ike_version_t version = IKEV2; u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED; + u_int16_t dh_grp = 0; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty; chunk_t secret = chunk_empty, old_skd = chunk_empty; chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty; @@ -193,6 +194,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message case HA_ALG_OLD_PRF: old_prf = value.u16; break; + case HA_ALG_DH: + dh_grp = value.u16; + break; default: break; } @@ -217,6 +221,10 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message { proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); } + if (dh_grp) + { + proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0); + } charon->bus->set_sa(charon->bus, ike_sa); dh = ha_diffie_hellman_create(secret, dh_local); if (ike_sa->get_version(ike_sa) == IKEV2) @@ -647,7 +655,7 @@ static void process_child_add(private_ha_dispatcher_t *this, u_int32_t inbound_spi = 0, outbound_spi = 0; u_int16_t inbound_cpi = 0, outbound_cpi = 0; u_int8_t mode = MODE_TUNNEL, ipcomp = 0; - u_int16_t encr = 0, integ = 0, len = 0; + u_int16_t encr = 0, integ = 0, len = 0, dh_grp = 0; u_int16_t esn = NO_EXT_SEQ_NUMBERS; u_int seg_i, seg_o; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; @@ -697,6 +705,9 @@ static void process_child_add(private_ha_dispatcher_t *this, case HA_ALG_INTEG: integ = value.u16; break; + case HA_ALG_DH: + dh_grp = value.u16; + break; case HA_ESN: esn = value.u16; break; @@ -747,6 +758,10 @@ static void process_child_add(private_ha_dispatcher_t *this, { proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); } + if (dh_grp) + { + proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0); + } proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); if (secret.len) { diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index 7492dd06e..3ffcaee6b 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -121,6 +121,10 @@ METHOD(listener_t, ike_keys, bool, { m->add_attribute(m, HA_ALG_PRF, alg); } + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL)) + { + m->add_attribute(m, HA_ALG_DH, alg); + } m->add_attribute(m, HA_NONCE_I, nonce_i); m->add_attribute(m, HA_NONCE_R, nonce_r); m->add_attribute(m, HA_SECRET, secret); @@ -310,27 +314,31 @@ METHOD(listener_t, message_hook, bool, sync_vips(this, ike_sa); } } - if (!plain && ike_sa->get_version(ike_sa) == IKEV1) + if (ike_sa->get_version(ike_sa) == IKEV1) { ha_message_t *m; keymat_v1_t *keymat; - u_int32_t mid; chunk_t iv; - mid = message->get_message_id(message); - if (mid == 0) + /* we need the last block (or expected next IV) of Phase 1, which gets + * upated after successful en-/decryption depending on direction */ + if (incoming == plain) { - keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); - if (keymat->get_iv(keymat, mid, &iv)) + if (message->get_message_id(message) == 0) { - m = ha_message_create(HA_IKE_IV); - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_IV, iv); - this->socket->push(this->socket, m); - this->cache->cache(this->cache, ike_sa, m); + keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + if (keymat->get_iv(keymat, 0, &iv)) + { + m = ha_message_create(HA_IKE_IV); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_IV, iv); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } } } - if (!incoming && message->get_exchange_type(message) == TRANSACTION) + if (!plain && !incoming && + message->get_exchange_type(message) == TRANSACTION) { sync_vips(this, ike_sa); } diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index 6b00ed83f..b40219ce1 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -230,6 +230,7 @@ METHOD(ha_message_t, add_attribute, void, break; } /* u_int16_t */ + case HA_ALG_DH: case HA_ALG_PRF: case HA_ALG_OLD_PRF: case HA_ALG_ENCR: @@ -450,6 +451,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, return TRUE; } /** u_int16_t */ + case HA_ALG_DH: case HA_ALG_PRF: case HA_ALG_OLD_PRF: case HA_ALG_ENCR: diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index 2ccb1fc55..fe1786edf 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -122,6 +122,8 @@ enum ha_message_attribute_t { HA_ALG_ENCR_LEN, /** u_int16_t, integrity protection algorithm */ HA_ALG_INTEG, + /** u_int16_t, DH group */ + HA_ALG_DH, /** u_int8_t, IPsec mode, TUNNEL|TRANSPORT|... */ HA_IPSEC_MODE, /** u_int8_t, IPComp protocol */ diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am index aed63c122..b8933008c 100644 --- a/src/libcharon/plugins/ipseckey/Makefile.am +++ b/src/libcharon/plugins/ipseckey/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in index f98e78ffc..0b7a29194 100644 --- a/src/libcharon/plugins/ipseckey/Makefile.in +++ b/src/libcharon/plugins/ipseckey/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/kernel_iph/Makefile.am b/src/libcharon/plugins/kernel_iph/Makefile.am index 56946ae1f..707570195 100644 --- a/src/libcharon/plugins/kernel_iph/Makefile.am +++ b/src/libcharon/plugins/kernel_iph/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in index 7a2583d06..de5bfd517 100644 --- a/src/libcharon/plugins/kernel_iph/Makefile.in +++ b/src/libcharon/plugins/kernel_iph/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c index a4be4041e..6a8a96821 100644 --- a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c +++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c @@ -24,7 +24,7 @@ #include "kernel_iph_net.h" -#include +#include #include #include #include @@ -130,7 +130,7 @@ static job_requeue_t roam_event(private_kernel_iph_net_t *this) this->roam_address = FALSE; this->mutex->unlock(this->mutex); - hydra->kernel_interface->roam(hydra->kernel_interface, address); + charon->kernel->roam(charon->kernel, address); return JOB_REQUEUE_NONE; } diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c index c5475e30b..c16381440 100644 --- a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c +++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c @@ -17,8 +17,6 @@ #include "kernel_iph_plugin.h" #include "kernel_iph_net.h" -#include - typedef struct private_kernel_iph_plugin_t private_kernel_iph_plugin_t; /** diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.am b/src/libcharon/plugins/kernel_libipsec/Makefile.am index eca2b2325..4757280b4 100644 --- a/src/libcharon/plugins/kernel_libipsec/Makefile.am +++ b/src/libcharon/plugins/kernel_libipsec/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libipsec diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in index 6b6c95688..018a25a62 100644 --- a/src/libcharon/plugins/kernel_libipsec/Makefile.in +++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libipsec diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c index d738e6d13..4c8771e96 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -224,8 +224,7 @@ static inline bool policy_entry_equals(policy_entry_t *a, */ static void expire(u_int8_t protocol, u_int32_t spi, host_t *dst, bool hard) { - hydra->kernel_interface->expire(hydra->kernel_interface, protocol, - spi, dst, hard); + charon->kernel->expire(charon->kernel, protocol, spi, dst, hard); } METHOD(kernel_ipsec_t, get_features, kernel_feature_t, @@ -313,16 +312,13 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this, if (!route->exclude) { DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src); - gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface, - dst, -1, NULL); + gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL); if (gtw) { char *if_name = NULL; - if (hydra->kernel_interface->get_interface( - hydra->kernel_interface, src, &if_name) && - hydra->kernel_interface->add_route(hydra->kernel_interface, - dst->get_address(dst), + if (charon->kernel->get_interface(charon->kernel, src, &if_name) && + charon->kernel->add_route(charon->kernel, dst->get_address(dst), dst->get_family(dst) == AF_INET ? 32 : 128, gtw, src, if_name) == SUCCESS) { @@ -367,14 +363,12 @@ static void remove_exclude_route(private_kernel_libipsec_ipsec_t *this, dst = route->exclude->dst; DBG2(DBG_KNL, "uninstalling exclude route for %H src %H", dst, route->exclude->src); - if (hydra->kernel_interface->get_interface( - hydra->kernel_interface, - route->exclude->src, &if_name) && - hydra->kernel_interface->del_route(hydra->kernel_interface, - dst->get_address(dst), - dst->get_family(dst) == AF_INET ? 32 : 128, - route->exclude->gtw, route->exclude->src, - if_name) != SUCCESS) + if (charon->kernel->get_interface(charon->kernel, route->exclude->src, + &if_name) && + charon->kernel->del_route(charon->kernel, dst->get_address(dst), + dst->get_family(dst) == AF_INET ? 32 : 128, + route->exclude->gtw, route->exclude->src, + if_name) != SUCCESS) { DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst); } @@ -402,8 +396,8 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this, return TRUE; } - if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface, - src_ts, &src_ip, &is_virtual) != SUCCESS) + if (charon->kernel->get_address_by_ts(charon->kernel, src_ts, &src_ip, + &is_virtual) != SUCCESS) { traffic_selector_t *multicast, *broadcast = NULL; bool ignore = FALSE; @@ -444,8 +438,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this, ); #ifndef __linux__ /* on Linux we cant't install a gateway */ - route->gateway = hydra->kernel_interface->get_nexthop( - hydra->kernel_interface, dst, -1, src); + route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1, src); #endif if (policy->route) @@ -459,9 +452,9 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this, return TRUE; } /* uninstall previously installed route */ - if (hydra->kernel_interface->del_route(hydra->kernel_interface, - old->dst_net, old->prefixlen, old->gateway, - old->src_ip, old->if_name) != SUCCESS) + if (charon->kernel->del_route(charon->kernel, old->dst_net, + old->prefixlen, old->gateway, + old->src_ip, old->if_name) != SUCCESS) { DBG1(DBG_KNL, "error uninstalling route installed with policy " "%R === %R %N", src_ts, dst_ts, policy_dir_names, @@ -490,9 +483,9 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this, DBG2(DBG_KNL, "installing route: %R src %H dev %s", dst_ts, route->src_ip, route->if_name); - switch (hydra->kernel_interface->add_route(hydra->kernel_interface, - route->dst_net, route->prefixlen, route->gateway, - route->src_ip, route->if_name)) + switch (charon->kernel->add_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name)) { case ALREADY_DONE: /* route exists, do not uninstall */ @@ -571,8 +564,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t, policy_entry_t *policy, *found = NULL; status_t status; - status = ipsec->policies->del_policy(ipsec->policies, src_ts, dst_ts, - direction, sa->reqid, mark, priority); + status = ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts, + dst_ts, direction, type, sa, mark, priority); policy = create_policy_entry(src_ts, dst_ts, direction); @@ -598,9 +591,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t, { route_entry_t *route = policy->route; - if (hydra->kernel_interface->del_route(hydra->kernel_interface, - route->dst_net, route->prefixlen, route->gateway, route->src_ip, - route->if_name) != SUCCESS) + if (charon->kernel->del_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name) != SUCCESS) { DBG1(DBG_KNL, "error uninstalling route installed with " "policy %R === %R %N", src_ts, dst_ts, @@ -629,9 +622,9 @@ METHOD(kernel_ipsec_t, flush_policies, status_t, { route_entry_t *route = pol->route; - hydra->kernel_interface->del_route(hydra->kernel_interface, - route->dst_net, route->prefixlen, route->gateway, - route->src_ip, route->if_name); + charon->kernel->del_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name); remove_exclude_route(this, route); } policy_entry_destroy(pol); diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c index 830954e11..66141ad56 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c @@ -19,7 +19,6 @@ #include "kernel_libipsec_router.h" #include -#include #include #include #include @@ -298,8 +297,7 @@ METHOD(kernel_libipsec_router_t, destroy, void, (ipsec_outbound_cb_t)send_esp); ipsec->processor->unregister_inbound(ipsec->processor, (ipsec_inbound_cb_t)deliver_plain); - hydra->kernel_interface->remove_listener(hydra->kernel_interface, - &this->public.listener); + charon->kernel->remove_listener(charon->kernel, &this->public.listener); this->lock->destroy(this->lock); this->tuns->destroy(this->tuns); close(this->notify[0]); @@ -351,8 +349,7 @@ kernel_libipsec_router_t *kernel_libipsec_router_create() (hashtable_equals_t)tun_entry_equals, 4); this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - hydra->kernel_interface->add_listener(hydra->kernel_interface, - &this->public.listener); + charon->kernel->add_listener(charon->kernel, &this->public.listener); ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL); ipsec->processor->register_inbound(ipsec->processor, (ipsec_inbound_cb_t)deliver_plain, this); diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.am b/src/libcharon/plugins/kernel_netlink/Makefile.am new file mode 100644 index 000000000..973e2c2f4 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/Makefile.am @@ -0,0 +1,44 @@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon \ + -DROUTING_TABLE=${routing_table} \ + -DROUTING_TABLE_PRIO=${routing_table_prio} + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la +else +plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la +endif + +libstrongswan_kernel_netlink_la_SOURCES = \ + kernel_netlink_plugin.h kernel_netlink_plugin.c \ + kernel_netlink_ipsec.h kernel_netlink_ipsec.c \ + kernel_netlink_net.h kernel_netlink_net.c \ + kernel_netlink_shared.h kernel_netlink_shared.c + +libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version + + +TESTS = tests + +check_PROGRAMS = $(TESTS) + +tests_SOURCES = \ + tests.h tests.c \ + suites/test_socket.c \ + kernel_netlink_shared.c + +tests_CFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libstrongswan/tests \ + -DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \ + @COVERAGE_CFLAGS@ + +tests_LDFLAGS = @COVERAGE_LDFLAGS@ +tests_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in new file mode 100644 index 000000000..55dcabf6f --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/Makefile.in @@ -0,0 +1,1007 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = tests$(EXEEXT) +check_PROGRAMS = $(am__EXEEXT_1) +subdir = src/libcharon/plugins/kernel_netlink +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_kernel_netlink_la_LIBADD = +am_libstrongswan_kernel_netlink_la_OBJECTS = kernel_netlink_plugin.lo \ + kernel_netlink_ipsec.lo kernel_netlink_net.lo \ + kernel_netlink_shared.lo +libstrongswan_kernel_netlink_la_OBJECTS = \ + $(am_libstrongswan_kernel_netlink_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_kernel_netlink_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_kernel_netlink_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_kernel_netlink_la_rpath = +am__EXEEXT_1 = tests$(EXEEXT) +am__dirstamp = $(am__leading_dot)dirstamp +am_tests_OBJECTS = tests-tests.$(OBJEXT) \ + suites/tests-test_socket.$(OBJEXT) \ + tests-kernel_netlink_shared.$(OBJEXT) +tests_OBJECTS = $(am_tests_OBJECTS) +tests_DEPENDENCIES = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la +tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(tests_CFLAGS) $(CFLAGS) \ + $(tests_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) $(tests_SOURCES) +DIST_SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) \ + $(tests_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon \ + -DROUTING_TABLE=${routing_table} \ + -DROUTING_TABLE_PRIO=${routing_table_prio} + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@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 +tests_SOURCES = \ + tests.h tests.c \ + suites/test_socket.c \ + kernel_netlink_shared.c + +tests_CFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libstrongswan/tests \ + -DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \ + @COVERAGE_CFLAGS@ + +tests_LDFLAGS = @COVERAGE_LDFLAGS@ +tests_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-kernel-netlink.la: $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_netlink_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +suites/$(am__dirstamp): + @$(MKDIR_P) suites + @: > suites/$(am__dirstamp) +suites/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) suites/$(DEPDIR) + @: > suites/$(DEPDIR)/$(am__dirstamp) +suites/tests-test_socket.$(OBJEXT): suites/$(am__dirstamp) \ + suites/$(DEPDIR)/$(am__dirstamp) + +tests$(EXEEXT): $(tests_OBJECTS) $(tests_DEPENDENCIES) $(EXTRA_tests_DEPENDENCIES) + @rm -f tests$(EXEEXT) + $(AM_V_CCLD)$(tests_LINK) $(tests_OBJECTS) $(tests_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f suites/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@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@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests-kernel_netlink_shared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests-tests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/tests-test_socket.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +tests-tests.o: tests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.o -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests.c' object='tests-tests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c + +tests-tests.obj: tests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.obj -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests.c' object='tests-tests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi` + +suites/tests-test_socket.o: suites/test_socket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.o -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c + +suites/tests-test_socket.obj: suites/test_socket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.obj -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi` + +tests-kernel_netlink_shared.o: kernel_netlink_shared.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.o -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c + +tests-kernel_netlink_shared.obj: kernel_netlink_shared.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.obj -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f suites/$(DEPDIR)/$(am__dirstamp) + -rm -f suites/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) suites/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) suites/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c new file mode 100644 index 000000000..6d9d63a98 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -0,0 +1,2975 @@ +/* + * Copyright (C) 2006-2015 Tobias Brunner + * Copyright (C) 2005-2009 Martin Willi + * Copyright (C) 2008-2016 Andreas Steffen + * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser + * Copyright (C) 2006 Daniel Roethlisberger + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kernel_netlink_ipsec.h" +#include "kernel_netlink_shared.h" + +#include +#include +#include +#include +#include +#include + +/** Required for Linux 2.6.26 kernel and later */ +#ifndef XFRM_STATE_AF_UNSPEC +#define XFRM_STATE_AF_UNSPEC 32 +#endif + +/** From linux/in.h */ +#ifndef IP_XFRM_POLICY +#define IP_XFRM_POLICY 17 +#endif + +/** Missing on uclibc */ +#ifndef IPV6_XFRM_POLICY +#define IPV6_XFRM_POLICY 34 +#endif /*IPV6_XFRM_POLICY*/ + +/* from linux/udp.h */ +#ifndef UDP_ENCAP +#define UDP_ENCAP 100 +#endif + +#ifndef UDP_ENCAP_ESPINUDP +#define UDP_ENCAP_ESPINUDP 2 +#endif + +/* this is not defined on some platforms */ +#ifndef SOL_UDP +#define SOL_UDP IPPROTO_UDP +#endif + +/** Base priority for installed policies */ +#define PRIO_BASE 384 + +/** Default lifetime of an acquire XFRM state (in seconds) */ +#define DEFAULT_ACQUIRE_LIFETIME 165 + +/** + * Map the limit for bytes and packets to XFRM_INF by default + */ +#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x)) + +/** + * Create ORable bitfield of XFRM NL groups + */ +#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1)) + +/** + * Returns a pointer to the first rtattr following the nlmsghdr *nlh and the + * 'usual' netlink data x like 'struct xfrm_usersa_info' + */ +#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \ + NLMSG_ALIGN(sizeof(x)))) +/** + * Returns the total size of attached rta data + * (after 'usual' netlink data x like 'struct xfrm_usersa_info') + */ +#define XFRM_PAYLOAD(nlh, x) NLMSG_PAYLOAD(nlh, sizeof(x)) + +typedef struct kernel_algorithm_t kernel_algorithm_t; + +/** + * Mapping of IKEv2 kernel identifier to linux crypto API names + */ +struct kernel_algorithm_t { + /** + * Identifier specified in IKEv2 + */ + int ikev2; + + /** + * Name of the algorithm in linux crypto API + */ + char *name; +}; + +ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING, + "XFRM_MSG_NEWSA", + "XFRM_MSG_DELSA", + "XFRM_MSG_GETSA", + "XFRM_MSG_NEWPOLICY", + "XFRM_MSG_DELPOLICY", + "XFRM_MSG_GETPOLICY", + "XFRM_MSG_ALLOCSPI", + "XFRM_MSG_ACQUIRE", + "XFRM_MSG_EXPIRE", + "XFRM_MSG_UPDPOLICY", + "XFRM_MSG_UPDSA", + "XFRM_MSG_POLEXPIRE", + "XFRM_MSG_FLUSHSA", + "XFRM_MSG_FLUSHPOLICY", + "XFRM_MSG_NEWAE", + "XFRM_MSG_GETAE", + "XFRM_MSG_REPORT", + "XFRM_MSG_MIGRATE", + "XFRM_MSG_NEWSADINFO", + "XFRM_MSG_GETSADINFO", + "XFRM_MSG_NEWSPDINFO", + "XFRM_MSG_GETSPDINFO", + "XFRM_MSG_MAPPING" +); + +ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_REPLAY_ESN_VAL, + "XFRMA_UNSPEC", + "XFRMA_ALG_AUTH", + "XFRMA_ALG_CRYPT", + "XFRMA_ALG_COMP", + "XFRMA_ENCAP", + "XFRMA_TMPL", + "XFRMA_SA", + "XFRMA_POLICY", + "XFRMA_SEC_CTX", + "XFRMA_LTIME_VAL", + "XFRMA_REPLAY_VAL", + "XFRMA_REPLAY_THRESH", + "XFRMA_ETIMER_THRESH", + "XFRMA_SRCADDR", + "XFRMA_COADDR", + "XFRMA_LASTUSED", + "XFRMA_POLICY_TYPE", + "XFRMA_MIGRATE", + "XFRMA_ALG_AEAD", + "XFRMA_KMADDRESS", + "XFRMA_ALG_AUTH_TRUNC", + "XFRMA_MARK", + "XFRMA_TFCPAD", + "XFRMA_REPLAY_ESN_VAL", +); + +/** + * Algorithms for encryption + */ +static kernel_algorithm_t encryption_algs[] = { +/* {ENCR_DES_IV64, "***" }, */ + {ENCR_DES, "des" }, + {ENCR_3DES, "des3_ede" }, +/* {ENCR_RC5, "***" }, */ +/* {ENCR_IDEA, "***" }, */ + {ENCR_CAST, "cast5" }, + {ENCR_BLOWFISH, "blowfish" }, +/* {ENCR_3IDEA, "***" }, */ +/* {ENCR_DES_IV32, "***" }, */ + {ENCR_NULL, "cipher_null" }, + {ENCR_AES_CBC, "aes" }, + {ENCR_AES_CTR, "rfc3686(ctr(aes))" }, + {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))" }, + {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))" }, + {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))" }, + {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))" }, + {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))" }, + {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))" }, + {ENCR_NULL_AUTH_AES_GMAC, "rfc4543(gcm(aes))" }, + {ENCR_CAMELLIA_CBC, "cbc(camellia)" }, +/* {ENCR_CAMELLIA_CTR, "***" }, */ +/* {ENCR_CAMELLIA_CCM_ICV8, "***" }, */ +/* {ENCR_CAMELLIA_CCM_ICV12, "***" }, */ +/* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */ + {ENCR_SERPENT_CBC, "serpent" }, + {ENCR_TWOFISH_CBC, "twofish" }, + {ENCR_CHACHA20_POLY1305, "rfc7539esp(chacha20,poly1305)"}, +}; + +/** + * Algorithms for integrity protection + */ +static kernel_algorithm_t integrity_algs[] = { + {AUTH_HMAC_MD5_96, "md5" }, + {AUTH_HMAC_MD5_128, "hmac(md5)" }, + {AUTH_HMAC_SHA1_96, "sha1" }, + {AUTH_HMAC_SHA1_160, "hmac(sha1)" }, + {AUTH_HMAC_SHA2_256_96, "sha256" }, + {AUTH_HMAC_SHA2_256_128, "hmac(sha256)" }, + {AUTH_HMAC_SHA2_384_192, "hmac(sha384)" }, + {AUTH_HMAC_SHA2_512_256, "hmac(sha512)" }, +/* {AUTH_DES_MAC, "***" }, */ +/* {AUTH_KPDK_MD5, "***" }, */ + {AUTH_AES_XCBC_96, "xcbc(aes)" }, +}; + +/** + * Algorithms for IPComp + */ +static kernel_algorithm_t compression_algs[] = { +/* {IPCOMP_OUI, "***" }, */ + {IPCOMP_DEFLATE, "deflate" }, + {IPCOMP_LZS, "lzs" }, + {IPCOMP_LZJH, "lzjh" }, +}; + +/** + * Look up a kernel algorithm name and its key size + */ +static char* lookup_algorithm(transform_type_t type, int ikev2) +{ + kernel_algorithm_t *list; + int i, count; + char *name; + + switch (type) + { + case ENCRYPTION_ALGORITHM: + list = encryption_algs; + count = countof(encryption_algs); + break; + case INTEGRITY_ALGORITHM: + list = integrity_algs; + count = countof(integrity_algs); + break; + case COMPRESSION_ALGORITHM: + list = compression_algs; + count = countof(compression_algs); + break; + default: + return NULL; + } + for (i = 0; i < count; i++) + { + if (list[i].ikev2 == ikev2) + { + return list[i].name; + } + } + if (charon->kernel->lookup_algorithm(charon->kernel, ikev2, type, NULL, + &name)) + { + return name; + } + return NULL; +} + +typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t; + +/** + * Private variables and functions of kernel_netlink class. + */ +struct private_kernel_netlink_ipsec_t { + /** + * Public part of the kernel_netlink_t object + */ + kernel_netlink_ipsec_t public; + + /** + * Mutex to lock access to installed policies + */ + mutex_t *mutex; + + /** + * Hash table of installed policies (policy_entry_t) + */ + hashtable_t *policies; + + /** + * Hash table of IPsec SAs using policies (ipsec_sa_t) + */ + hashtable_t *sas; + + /** + * Netlink xfrm socket (IPsec) + */ + netlink_socket_t *socket_xfrm; + + /** + * Netlink xfrm socket to receive acquire and expire events + */ + int socket_xfrm_events; + + /** + * Whether to install routes along policies + */ + bool install_routes; + + /** + * Whether to set protocol and ports on selector installed with transport + * mode IPsec SAs + */ + bool proto_port_transport; + + /** + * Whether to always use UPDATE to install policies + */ + bool policy_update; + + /** + * Installed port based IKE bypass policies, as bypass_t + */ + array_t *bypass; +}; + +typedef struct route_entry_t route_entry_t; + +/** + * Installed routing entry + */ +struct route_entry_t { + /** Name of the interface the route is bound to */ + char *if_name; + + /** Source ip of the route */ + host_t *src_ip; + + /** Gateway for this route */ + host_t *gateway; + + /** Destination net */ + chunk_t dst_net; + + /** Destination net prefixlen */ + u_int8_t prefixlen; +}; + +/** + * Destroy a route_entry_t object + */ +static void route_entry_destroy(route_entry_t *this) +{ + free(this->if_name); + this->src_ip->destroy(this->src_ip); + DESTROY_IF(this->gateway); + chunk_free(&this->dst_net); + free(this); +} + +/** + * Compare two route_entry_t objects + */ +static bool route_entry_equals(route_entry_t *a, route_entry_t *b) +{ + return a->if_name && b->if_name && streq(a->if_name, b->if_name) && + a->src_ip->ip_equals(a->src_ip, b->src_ip) && + a->gateway->ip_equals(a->gateway, b->gateway) && + chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen; +} + +typedef struct ipsec_sa_t ipsec_sa_t; + +/** + * IPsec SA assigned to a policy. + */ +struct ipsec_sa_t { + /** Source address of this SA */ + host_t *src; + + /** Destination address of this SA */ + host_t *dst; + + /** Optional mark */ + mark_t mark; + + /** Description of this SA */ + ipsec_sa_cfg_t cfg; + + /** Reference count for this SA */ + refcount_t refcount; +}; + +/** + * Hash function for ipsec_sa_t objects + */ +static u_int ipsec_sa_hash(ipsec_sa_t *sa) +{ + return chunk_hash_inc(sa->src->get_address(sa->src), + chunk_hash_inc(sa->dst->get_address(sa->dst), + chunk_hash_inc(chunk_from_thing(sa->mark), + chunk_hash(chunk_from_thing(sa->cfg))))); +} + +/** + * Equality function for ipsec_sa_t objects + */ +static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa) +{ + return sa->src->ip_equals(sa->src, other_sa->src) && + sa->dst->ip_equals(sa->dst, other_sa->dst) && + memeq(&sa->mark, &other_sa->mark, sizeof(mark_t)) && + memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t)); +} + +/** + * Allocate or reference an IPsec SA object + */ +static ipsec_sa_t *ipsec_sa_create(private_kernel_netlink_ipsec_t *this, + host_t *src, host_t *dst, mark_t mark, + ipsec_sa_cfg_t *cfg) +{ + ipsec_sa_t *sa, *found; + INIT(sa, + .src = src, + .dst = dst, + .mark = mark, + .cfg = *cfg, + ); + found = this->sas->get(this->sas, sa); + if (!found) + { + sa->src = src->clone(src); + sa->dst = dst->clone(dst); + this->sas->put(this->sas, sa, sa); + } + else + { + free(sa); + sa = found; + } + ref_get(&sa->refcount); + return sa; +} + +/** + * Release and destroy an IPsec SA object + */ +static void ipsec_sa_destroy(private_kernel_netlink_ipsec_t *this, + ipsec_sa_t *sa) +{ + if (ref_put(&sa->refcount)) + { + this->sas->remove(this->sas, sa); + DESTROY_IF(sa->src); + DESTROY_IF(sa->dst); + free(sa); + } +} + +typedef struct policy_sa_t policy_sa_t; +typedef struct policy_sa_fwd_t policy_sa_fwd_t; + +/** + * Mapping between a policy and an IPsec SA. + */ +struct policy_sa_t { + /** Priority assigned to the policy when installed with this SA */ + u_int32_t priority; + + /** Type of the policy */ + policy_type_t type; + + /** Assigned SA */ + ipsec_sa_t *sa; +}; + +/** + * For forward policies we also cache the traffic selectors in order to install + * the route. + */ +struct policy_sa_fwd_t { + /** Generic interface */ + policy_sa_t generic; + + /** Source traffic selector of this policy */ + traffic_selector_t *src_ts; + + /** Destination traffic selector of this policy */ + traffic_selector_t *dst_ts; +}; + +/** + * Create a policy_sa(_fwd)_t object + */ +static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this, + policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, mark_t mark, + ipsec_sa_cfg_t *cfg) +{ + policy_sa_t *policy; + + if (dir == POLICY_FWD) + { + policy_sa_fwd_t *fwd; + INIT(fwd, + .src_ts = src_ts->clone(src_ts), + .dst_ts = dst_ts->clone(dst_ts), + ); + policy = &fwd->generic; + } + else + { + INIT(policy, .priority = 0); + } + policy->type = type; + policy->sa = ipsec_sa_create(this, src, dst, mark, cfg); + return policy; +} + +/** + * Destroy a policy_sa(_fwd)_t object + */ +static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir, + private_kernel_netlink_ipsec_t *this) +{ + if (*dir == POLICY_FWD) + { + policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)policy; + fwd->src_ts->destroy(fwd->src_ts); + fwd->dst_ts->destroy(fwd->dst_ts); + } + ipsec_sa_destroy(this, policy->sa); + free(policy); +} + +typedef struct policy_entry_t policy_entry_t; + +/** + * Installed kernel policy. + */ +struct policy_entry_t { + + /** Direction of this policy: in, out, forward */ + u_int8_t direction; + + /** Parameters of installed policy */ + struct xfrm_selector sel; + + /** Optional mark */ + u_int32_t mark; + + /** Associated route installed for this policy */ + route_entry_t *route; + + /** List of SAs this policy is used by, ordered by priority */ + linked_list_t *used_by; + + /** reqid for this policy */ + u_int32_t reqid; +}; + +/** + * Destroy a policy_entry_t object + */ +static void policy_entry_destroy(private_kernel_netlink_ipsec_t *this, + policy_entry_t *policy) +{ + if (policy->route) + { + route_entry_destroy(policy->route); + } + if (policy->used_by) + { + policy->used_by->invoke_function(policy->used_by, + (linked_list_invoke_t)policy_sa_destroy, + &policy->direction, this); + policy->used_by->destroy(policy->used_by); + } + free(policy); +} + +/** + * Hash function for policy_entry_t objects + */ +static u_int policy_hash(policy_entry_t *key) +{ + chunk_t chunk = chunk_from_thing(key->sel); + return chunk_hash_inc(chunk, chunk_hash(chunk_from_thing(key->mark))); +} + +/** + * Equality function for policy_entry_t objects + */ +static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key) +{ + return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) && + key->mark == other_key->mark && + key->direction == other_key->direction; +} + +/** + * Calculate the priority of a policy + */ +static inline u_int32_t get_priority(policy_entry_t *policy, + policy_priority_t prio) +{ + u_int32_t priority = PRIO_BASE; + switch (prio) + { + case POLICY_PRIORITY_FALLBACK: + priority <<= 1; + /* fall-through */ + case POLICY_PRIORITY_ROUTED: + priority <<= 1; + /* fall-through */ + case POLICY_PRIORITY_DEFAULT: + priority <<= 1; + /* fall-through */ + case POLICY_PRIORITY_PASS: + break; + } + /* calculate priority based on selector size, small size = high prio */ + priority -= policy->sel.prefixlen_s; + priority -= policy->sel.prefixlen_d; + priority <<= 2; /* make some room for the two flags */ + priority += policy->sel.sport_mask || policy->sel.dport_mask ? 0 : 2; + priority += policy->sel.proto ? 0 : 1; + return priority; +} + +/** + * Convert the general ipsec mode to the one defined in xfrm.h + */ +static u_int8_t mode2kernel(ipsec_mode_t mode) +{ + switch (mode) + { + case MODE_TRANSPORT: + return XFRM_MODE_TRANSPORT; + case MODE_TUNNEL: + return XFRM_MODE_TUNNEL; + case MODE_BEET: + return XFRM_MODE_BEET; + default: + return mode; + } +} + +/** + * Convert a host_t to a struct xfrm_address + */ +static void host2xfrm(host_t *host, xfrm_address_t *xfrm) +{ + chunk_t chunk = host->get_address(host); + memcpy(xfrm, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t))); +} + +/** + * Convert a struct xfrm_address to a host_t + */ +static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port) +{ + chunk_t chunk; + + switch (family) + { + case AF_INET: + chunk = chunk_create((u_char*)&xfrm->a4, sizeof(xfrm->a4)); + break; + case AF_INET6: + chunk = chunk_create((u_char*)&xfrm->a6, sizeof(xfrm->a6)); + break; + default: + return NULL; + } + return host_create_from_chunk(family, chunk, ntohs(port)); +} + +/** + * Convert a traffic selector address range to subnet and its mask. + */ +static void ts2subnet(traffic_selector_t* ts, + xfrm_address_t *net, u_int8_t *mask) +{ + host_t *net_host; + chunk_t net_chunk; + + ts->to_subnet(ts, &net_host, mask); + net_chunk = net_host->get_address(net_host); + memcpy(net, net_chunk.ptr, net_chunk.len); + net_host->destroy(net_host); +} + +/** + * Convert a traffic selector port range to port/portmask + */ +static void ts2ports(traffic_selector_t* ts, + u_int16_t *port, u_int16_t *mask) +{ + uint16_t from, to, bitmask; + int bit; + + from = ts->get_from_port(ts); + to = ts->get_to_port(ts); + + /* Quick check for a single port */ + if (from == to) + { + *port = htons(from); + *mask = ~0; + } + else + { + /* Compute the port mask for port ranges */ + *mask = 0; + + for (bit = 15; bit >= 0; bit--) + { + bitmask = 1 << bit; + + if ((bitmask & from) != (bitmask & to)) + { + *port = htons(from & *mask); + *mask = htons(*mask); + return; + } + *mask |= bitmask; + } + } + return; +} + +/** + * Convert a pair of traffic_selectors to an xfrm_selector + */ +static struct xfrm_selector ts2selector(traffic_selector_t *src, + traffic_selector_t *dst) +{ + struct xfrm_selector sel; + u_int16_t port; + + memset(&sel, 0, sizeof(sel)); + sel.family = (src->get_type(src) == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6; + /* src or dest proto may be "any" (0), use more restrictive one */ + sel.proto = max(src->get_protocol(src), dst->get_protocol(dst)); + ts2subnet(dst, &sel.daddr, &sel.prefixlen_d); + ts2subnet(src, &sel.saddr, &sel.prefixlen_s); + ts2ports(dst, &sel.dport, &sel.dport_mask); + ts2ports(src, &sel.sport, &sel.sport_mask); + if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) && + (sel.dport || sel.sport)) + { + /* the kernel expects the ICMP type and code in the source and + * destination port fields, respectively. */ + port = ntohs(max(sel.dport, sel.sport)); + sel.sport = htons(traffic_selector_icmp_type(port)); + sel.sport_mask = sel.sport ? ~0 : 0; + sel.dport = htons(traffic_selector_icmp_code(port)); + sel.dport_mask = sel.dport ? ~0 : 0; + } + sel.ifindex = 0; + sel.user = 0; + + return sel; +} + +/** + * Convert an xfrm_selector to a src|dst traffic_selector + */ +static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) +{ + u_char *addr; + u_int8_t prefixlen; + u_int16_t port = 0; + host_t *host = NULL; + + if (src) + { + addr = (u_char*)&sel->saddr; + prefixlen = sel->prefixlen_s; + if (sel->sport_mask) + { + port = ntohs(sel->sport); + } + } + else + { + addr = (u_char*)&sel->daddr; + prefixlen = sel->prefixlen_d; + if (sel->dport_mask) + { + port = ntohs(sel->dport); + } + } + if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6) + { /* convert ICMP[v6] message type and code as supplied by the kernel in + * source and destination ports (both in network order) */ + port = (sel->sport >> 8) | (sel->dport & 0xff00); + port = ntohs(port); + } + /* The Linux 2.6 kernel does not set the selector's family field, + * so as a kludge we additionally test the prefix length. + */ + if (sel->family == AF_INET || sel->prefixlen_s == 32) + { + host = host_create_from_chunk(AF_INET, chunk_create(addr, 4), 0); + } + else if (sel->family == AF_INET6 || sel->prefixlen_s == 128) + { + host = host_create_from_chunk(AF_INET6, chunk_create(addr, 16), 0); + } + + if (host) + { + return traffic_selector_create_from_subnet(host, prefixlen, + sel->proto, port, port ?: 65535); + } + return NULL; +} + +/** + * Process a XFRM_MSG_ACQUIRE from kernel + */ +static void process_acquire(private_kernel_netlink_ipsec_t *this, + struct nlmsghdr *hdr) +{ + struct xfrm_user_acquire *acquire; + struct rtattr *rta; + size_t rtasize; + traffic_selector_t *src_ts, *dst_ts; + u_int32_t reqid = 0; + int proto = 0; + + acquire = NLMSG_DATA(hdr); + rta = XFRM_RTA(hdr, struct xfrm_user_acquire); + rtasize = XFRM_PAYLOAD(hdr, struct xfrm_user_acquire); + + DBG2(DBG_KNL, "received a XFRM_MSG_ACQUIRE"); + + while (RTA_OK(rta, rtasize)) + { + DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type); + + if (rta->rta_type == XFRMA_TMPL) + { + struct xfrm_user_tmpl* tmpl; + tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rta); + reqid = tmpl->reqid; + proto = tmpl->id.proto; + } + rta = RTA_NEXT(rta, rtasize); + } + switch (proto) + { + case 0: + case IPPROTO_ESP: + case IPPROTO_AH: + break; + default: + /* acquire for AH/ESP only, not for IPCOMP */ + return; + } + src_ts = selector2ts(&acquire->sel, TRUE); + dst_ts = selector2ts(&acquire->sel, FALSE); + + charon->kernel->acquire(charon->kernel, reqid, src_ts, dst_ts); +} + +/** + * Process a XFRM_MSG_EXPIRE from kernel + */ +static void process_expire(private_kernel_netlink_ipsec_t *this, + struct nlmsghdr *hdr) +{ + struct xfrm_user_expire *expire; + u_int32_t spi; + u_int8_t protocol; + host_t *dst; + + expire = NLMSG_DATA(hdr); + protocol = expire->state.id.proto; + spi = expire->state.id.spi; + + DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE"); + + if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH) + { + dst = xfrm2host(expire->state.family, &expire->state.id.daddr, 0); + if (dst) + { + charon->kernel->expire(charon->kernel, protocol, spi, dst, + expire->hard != 0); + dst->destroy(dst); + } + } +} + +/** + * Process a XFRM_MSG_MIGRATE from kernel + */ +static void process_migrate(private_kernel_netlink_ipsec_t *this, + struct nlmsghdr *hdr) +{ + struct xfrm_userpolicy_id *policy_id; + struct rtattr *rta; + size_t rtasize; + traffic_selector_t *src_ts, *dst_ts; + host_t *local = NULL, *remote = NULL; + host_t *old_src = NULL, *old_dst = NULL; + host_t *new_src = NULL, *new_dst = NULL; + u_int32_t reqid = 0; + policy_dir_t dir; + + policy_id = NLMSG_DATA(hdr); + rta = XFRM_RTA(hdr, struct xfrm_userpolicy_id); + rtasize = XFRM_PAYLOAD(hdr, struct xfrm_userpolicy_id); + + DBG2(DBG_KNL, "received a XFRM_MSG_MIGRATE"); + + src_ts = selector2ts(&policy_id->sel, TRUE); + dst_ts = selector2ts(&policy_id->sel, FALSE); + dir = (policy_dir_t)policy_id->dir; + + DBG2(DBG_KNL, " policy: %R === %R %N", src_ts, dst_ts, policy_dir_names); + + while (RTA_OK(rta, rtasize)) + { + DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type); + if (rta->rta_type == XFRMA_KMADDRESS) + { + struct xfrm_user_kmaddress *kmaddress; + + kmaddress = (struct xfrm_user_kmaddress*)RTA_DATA(rta); + local = xfrm2host(kmaddress->family, &kmaddress->local, 0); + remote = xfrm2host(kmaddress->family, &kmaddress->remote, 0); + DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote); + } + else if (rta->rta_type == XFRMA_MIGRATE) + { + struct xfrm_user_migrate *migrate; + + migrate = (struct xfrm_user_migrate*)RTA_DATA(rta); + old_src = xfrm2host(migrate->old_family, &migrate->old_saddr, 0); + old_dst = xfrm2host(migrate->old_family, &migrate->old_daddr, 0); + new_src = xfrm2host(migrate->new_family, &migrate->new_saddr, 0); + new_dst = xfrm2host(migrate->new_family, &migrate->new_daddr, 0); + reqid = migrate->reqid; + DBG2(DBG_KNL, " migrate %H...%H to %H...%H, reqid {%u}", + old_src, old_dst, new_src, new_dst, reqid); + DESTROY_IF(old_src); + DESTROY_IF(old_dst); + DESTROY_IF(new_src); + DESTROY_IF(new_dst); + } + rta = RTA_NEXT(rta, rtasize); + } + + if (src_ts && dst_ts && local && remote) + { + charon->kernel->migrate(charon->kernel, reqid, src_ts, dst_ts, dir, + local, remote); + } + else + { + DESTROY_IF(src_ts); + DESTROY_IF(dst_ts); + DESTROY_IF(local); + DESTROY_IF(remote); + } +} + +/** + * Process a XFRM_MSG_MAPPING from kernel + */ +static void process_mapping(private_kernel_netlink_ipsec_t *this, + struct nlmsghdr *hdr) +{ + struct xfrm_user_mapping *mapping; + u_int32_t spi; + + mapping = NLMSG_DATA(hdr); + spi = mapping->id.spi; + + DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING"); + + if (mapping->id.proto == IPPROTO_ESP) + { + host_t *dst, *new; + + dst = xfrm2host(mapping->id.family, &mapping->id.daddr, 0); + if (dst) + { + new = xfrm2host(mapping->id.family, &mapping->new_saddr, + mapping->new_sport); + if (new) + { + charon->kernel->mapping(charon->kernel, IPPROTO_ESP, spi, dst, + new); + new->destroy(new); + } + dst->destroy(dst); + } + } +} + +/** + * Receives events from kernel + */ +static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd, + watcher_event_t event) +{ + char response[1024]; + struct nlmsghdr *hdr = (struct nlmsghdr*)response; + struct sockaddr_nl addr; + socklen_t addr_len = sizeof(addr); + int len; + + len = recvfrom(this->socket_xfrm_events, response, sizeof(response), + MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len); + if (len < 0) + { + switch (errno) + { + case EINTR: + /* interrupted, try again */ + return TRUE; + case EAGAIN: + /* no data ready, select again */ + return TRUE; + default: + DBG1(DBG_KNL, "unable to receive from xfrm event socket"); + sleep(1); + return TRUE; + } + } + + if (addr.nl_pid != 0) + { /* not from kernel. not interested, try another one */ + return TRUE; + } + + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_ACQUIRE: + process_acquire(this, hdr); + break; + case XFRM_MSG_EXPIRE: + process_expire(this, hdr); + break; + case XFRM_MSG_MIGRATE: + process_migrate(this, hdr); + break; + case XFRM_MSG_MAPPING: + process_mapping(this, hdr); + break; + default: + DBG1(DBG_KNL, "received unknown event from xfrm event " + "socket: %d", hdr->nlmsg_type); + break; + } + hdr = NLMSG_NEXT(hdr, len); + } + return TRUE; +} + +METHOD(kernel_ipsec_t, get_features, kernel_feature_t, + private_kernel_netlink_ipsec_t *this) +{ + return KERNEL_ESP_V3_TFC; +} + +/** + * Get an SPI for a specific protocol from the kernel. + */ +static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this, + host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max, + u_int32_t *spi) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out; + struct xfrm_userspi_info *userspi; + u_int32_t received_spi = 0; + size_t len; + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_ALLOCSPI; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info)); + + userspi = NLMSG_DATA(hdr); + host2xfrm(src, &userspi->info.saddr); + host2xfrm(dst, &userspi->info.id.daddr); + userspi->info.id.proto = proto; + userspi->info.mode = XFRM_MODE_TUNNEL; + userspi->info.family = src->get_family(src); + userspi->min = min; + userspi->max = max; + + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWSA: + { + struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr); + received_spi = usersa->id.spi; + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + DBG1(DBG_KNL, "allocating SPI failed: %s (%d)", + strerror(-err->error), -err->error); + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + free(out); + } + + if (received_spi == 0) + { + return FAILED; + } + + *spi = received_spi; + return SUCCESS; +} + +METHOD(kernel_ipsec_t, get_spi, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t *spi) +{ + if (get_spi_internal(this, src, dst, protocol, + 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get SPI"); + return FAILED; + } + + DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi)); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, get_cpi, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + u_int16_t *cpi) +{ + u_int32_t received_spi = 0; + + if (get_spi_internal(this, src, dst, IPPROTO_COMP, + 0x100, 0xEFFF, &received_spi) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get CPI"); + return FAILED; + } + + *cpi = htons((u_int16_t)ntohl(received_spi)); + + DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi)); + return SUCCESS; +} + +/** + * Add a XFRM mark to message if required + */ +static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark) +{ + if (mark.value) + { + struct xfrm_mark *xmrk; + + xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk)); + if (!xmrk) + { + return FALSE; + } + xmrk->v = mark.value; + xmrk->m = mark.mask; + } + return TRUE; +} + +METHOD(kernel_ipsec_t, add_sa, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, + u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t* src_ts, linked_list_t* dst_ts) +{ + netlink_buf_t request; + char *alg_name; + struct nlmsghdr *hdr; + struct xfrm_usersa_info *sa; + u_int16_t icv_size = 64; + ipsec_mode_t original_mode = mode; + traffic_selector_t *first_src_ts, *first_dst_ts; + status_t status = FAILED; + + /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0 + * we are in the recursive call below */ + if (ipcomp != IPCOMP_NONE && cpi != 0) + { + lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}}; + add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, + tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, + chunk_empty, mode, ipcomp, 0, 0, initiator, FALSE, FALSE, + inbound, update, src_ts, dst_ts); + ipcomp = IPCOMP_NONE; + /* use transport mode ESP SA, IPComp uses tunnel mode */ + mode = MODE_TRANSPORT; + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} (mark " + "%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)); + + sa = NLMSG_DATA(hdr); + host2xfrm(src, &sa->saddr); + host2xfrm(dst, &sa->id.daddr); + sa->id.spi = spi; + sa->id.proto = protocol; + sa->family = src->get_family(src); + sa->mode = mode2kernel(mode); + switch (mode) + { + case MODE_TUNNEL: + sa->flags |= XFRM_STATE_AF_UNSPEC; + break; + case MODE_BEET: + case MODE_TRANSPORT: + if (original_mode == MODE_TUNNEL) + { /* don't install selectors for switched SAs. because only one + * selector can be installed other traffic would get dropped */ + break; + } + if (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS && + dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS) + { + sa->sel = ts2selector(first_src_ts, first_dst_ts); + if (!this->proto_port_transport) + { + /* don't install proto/port on SA. This would break + * potential secondary SAs for the same address using a + * different prot/port. */ + sa->sel.proto = 0; + sa->sel.dport = sa->sel.dport_mask = 0; + sa->sel.sport = sa->sel.sport_mask = 0; + } + } + break; + default: + break; + } + + sa->reqid = reqid; + sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey); + sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life); + sa->lft.soft_packet_limit = XFRM_LIMIT(lifetime->packets.rekey); + sa->lft.hard_packet_limit = XFRM_LIMIT(lifetime->packets.life); + /* we use lifetimes since added, not since used */ + sa->lft.soft_add_expires_seconds = lifetime->time.rekey; + sa->lft.hard_add_expires_seconds = lifetime->time.life; + sa->lft.soft_use_expires_seconds = 0; + sa->lft.hard_use_expires_seconds = 0; + + switch (enc_alg) + { + case ENCR_UNDEFINED: + /* no encryption */ + break; + case ENCR_AES_CCM_ICV16: + case ENCR_AES_GCM_ICV16: + case ENCR_NULL_AUTH_AES_GMAC: + case ENCR_CAMELLIA_CCM_ICV16: + case ENCR_CHACHA20_POLY1305: + icv_size += 32; + /* FALL */ + case ENCR_AES_CCM_ICV12: + case ENCR_AES_GCM_ICV12: + case ENCR_CAMELLIA_CCM_ICV12: + icv_size += 32; + /* FALL */ + case ENCR_AES_CCM_ICV8: + case ENCR_AES_GCM_ICV8: + case ENCR_CAMELLIA_CCM_ICV8: + { + struct xfrm_algo_aead *algo; + + alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + encryption_algorithm_names, enc_alg); + goto failed; + } + DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", + encryption_algorithm_names, enc_alg, enc_key.len * 8); + + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD, + sizeof(*algo) + enc_key.len); + if (!algo) + { + goto failed; + } + algo->alg_key_len = enc_key.len * 8; + algo->alg_icv_len = icv_size; + strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); + algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; + memcpy(algo->alg_key, enc_key.ptr, enc_key.len); + break; + } + default: + { + struct xfrm_algo *algo; + + alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + encryption_algorithm_names, enc_alg); + goto failed; + } + DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", + encryption_algorithm_names, enc_alg, enc_key.len * 8); + + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT, + sizeof(*algo) + enc_key.len); + if (!algo) + { + goto failed; + } + algo->alg_key_len = enc_key.len * 8; + strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); + algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; + memcpy(algo->alg_key, enc_key.ptr, enc_key.len); + } + } + + if (int_alg != AUTH_UNDEFINED) + { + u_int trunc_len = 0; + + alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + integrity_algorithm_names, int_alg); + goto failed; + } + DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", + integrity_algorithm_names, int_alg, int_key.len * 8); + + switch (int_alg) + { + case AUTH_HMAC_MD5_128: + case AUTH_HMAC_SHA2_256_128: + trunc_len = 128; + break; + case AUTH_HMAC_SHA1_160: + trunc_len = 160; + break; + default: + break; + } + + if (trunc_len) + { + struct xfrm_algo_auth* algo; + + /* the kernel uses SHA256 with 96 bit truncation by default, + * use specified truncation size supported by newer kernels. + * also use this for untruncated MD5 and SHA1. */ + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC, + sizeof(*algo) + int_key.len); + if (!algo) + { + goto failed; + } + algo->alg_key_len = int_key.len * 8; + algo->alg_trunc_len = trunc_len; + strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); + algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; + memcpy(algo->alg_key, int_key.ptr, int_key.len); + } + else + { + struct xfrm_algo* algo; + + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH, + sizeof(*algo) + int_key.len); + if (!algo) + { + goto failed; + } + algo->alg_key_len = int_key.len * 8; + strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); + algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; + memcpy(algo->alg_key, int_key.ptr, int_key.len); + } + } + + if (ipcomp != IPCOMP_NONE) + { + struct xfrm_algo* algo; + + alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + ipcomp_transform_names, ipcomp); + goto failed; + } + DBG2(DBG_KNL, " using compression algorithm %N", + ipcomp_transform_names, ipcomp); + + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP, + sizeof(*algo)); + if (!algo) + { + goto failed; + } + algo->alg_key_len = 0; + strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); + algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; + } + + if (encap) + { + struct xfrm_encap_tmpl *tmpl; + + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl)); + if (!tmpl) + { + goto failed; + } + tmpl->encap_type = UDP_ENCAP_ESPINUDP; + tmpl->encap_sport = htons(src->get_port(src)); + tmpl->encap_dport = htons(dst->get_port(dst)); + memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t)); + /* encap_oa could probably be derived from the + * traffic selectors [rfc4306, p39]. In the netlink kernel + * implementation pluto does the same as we do here but it uses + * encap_oa in the pfkey implementation. + * BUT as /usr/src/linux/net/key/af_key.c indicates the kernel ignores + * it anyway + * -> does that mean that NAT-T encap doesn't work in transport mode? + * No. The reason the kernel ignores NAT-OA is that it recomputes + * (or, rather, just ignores) the checksum. If packets pass the IPsec + * checks it marks them "checksum ok" so OA isn't needed. */ + } + + if (!add_mark(hdr, sizeof(request), mark)) + { + goto failed; + } + + if (tfc && protocol == IPPROTO_ESP && mode == MODE_TUNNEL) + { /* the kernel supports TFC padding only for tunnel mode ESP SAs */ + u_int32_t *tfcpad; + + tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD, + sizeof(*tfcpad)); + if (!tfcpad) + { + goto failed; + } + *tfcpad = tfc; + } + + if (protocol != IPPROTO_COMP) + { + if (replay_window != 0 && (esn || replay_window > 32)) + { + /* for ESN or larger replay windows we need the new + * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */ + struct xfrm_replay_state_esn *replay; + u_int32_t bmp_size; + + bmp_size = round_up(replay_window, sizeof(u_int32_t) * 8) / 8; + replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL, + sizeof(*replay) + bmp_size); + if (!replay) + { + goto failed; + } + /* bmp_len contains number uf __u32's */ + replay->bmp_len = bmp_size / sizeof(u_int32_t); + replay->replay_window = replay_window; + DBG2(DBG_KNL, " using replay window of %u packets", replay_window); + + if (esn) + { + DBG2(DBG_KNL, " using extended sequence numbers (ESN)"); + sa->flags |= XFRM_STATE_ESN; + } + } + else + { + DBG2(DBG_KNL, " using replay window of %u packets", replay_window); + sa->replay_window = replay_window; + } + } + + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) + { + if (mark.value) + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x " + "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); + } + goto failed; + } + + status = SUCCESS; + +failed: + memwipe(&request, sizeof(request)); + return status; +} + +/** + * Get the ESN replay state (i.e. sequence numbers) of an SA. + * + * Allocates into one the replay state structure we get from the kernel. + */ +static void get_replay_state(private_kernel_netlink_ipsec_t *this, + u_int32_t spi, u_int8_t protocol, + host_t *dst, mark_t mark, + struct xfrm_replay_state_esn **replay_esn, + u_int32_t *replay_esn_len, + struct xfrm_replay_state **replay, + struct xfrm_lifetime_cur **lifetime) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out = NULL; + struct xfrm_aevent_id *out_aevent = NULL, *aevent_id; + size_t len; + struct rtattr *rta; + size_t rtasize; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x", + ntohl(spi)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_GETAE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); + + aevent_id = NLMSG_DATA(hdr); + aevent_id->flags = XFRM_AE_RVAL; + + host2xfrm(dst, &aevent_id->sa_id.daddr); + aevent_id->sa_id.spi = spi; + aevent_id->sa_id.proto = protocol; + aevent_id->sa_id.family = dst->get_family(dst); + + if (!add_mark(hdr, sizeof(request), mark)) + { + return; + } + + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWAE: + { + out_aevent = NLMSG_DATA(hdr); + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + DBG1(DBG_KNL, "querying replay state from SAD entry " + "failed: %s (%d)", strerror(-err->error), + -err->error); + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + } + + if (out_aevent) + { + rta = XFRM_RTA(out, struct xfrm_aevent_id); + rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id); + while (RTA_OK(rta, rtasize)) + { + if (rta->rta_type == XFRMA_LTIME_VAL && + RTA_PAYLOAD(rta) == sizeof(**lifetime)) + { + free(*lifetime); + *lifetime = malloc(RTA_PAYLOAD(rta)); + memcpy(*lifetime, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + if (rta->rta_type == XFRMA_REPLAY_VAL && + RTA_PAYLOAD(rta) == sizeof(**replay)) + { + free(*replay); + *replay = malloc(RTA_PAYLOAD(rta)); + memcpy(*replay, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + if (rta->rta_type == XFRMA_REPLAY_ESN_VAL && + RTA_PAYLOAD(rta) >= sizeof(**replay_esn)) + { + free(*replay_esn); + *replay_esn = malloc(RTA_PAYLOAD(rta)); + *replay_esn_len = RTA_PAYLOAD(rta); + memcpy(*replay_esn, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + rta = RTA_NEXT(rta, rtasize); + } + } + free(out); +} + +METHOD(kernel_ipsec_t, query_sa, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, + u_int64_t *bytes, u_int64_t *packets, time_t *time) +{ + netlink_buf_t request; + struct nlmsghdr *out = NULL, *hdr; + struct xfrm_usersa_id *sa_id; + struct xfrm_usersa_info *sa = NULL; + status_t status = FAILED; + size_t len; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%08x)", + ntohl(spi), mark.value, mark.mask); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_GETSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)); + + sa_id = NLMSG_DATA(hdr); + host2xfrm(dst, &sa_id->daddr); + sa_id->spi = spi; + sa_id->proto = protocol; + sa_id->family = dst->get_family(dst); + + if (!add_mark(hdr, sizeof(request), mark)) + { + return FAILED; + } + + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWSA: + { + sa = NLMSG_DATA(hdr); + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + + if (mark.value) + { + DBG1(DBG_KNL, "querying SAD entry with SPI %.8x " + "(mark %u/0x%08x) failed: %s (%d)", + ntohl(spi), mark.value, mark.mask, + strerror(-err->error), -err->error); + } + else + { + DBG1(DBG_KNL, "querying SAD entry with SPI %.8x " + "failed: %s (%d)", ntohl(spi), + strerror(-err->error), -err->error); + } + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + } + + if (sa == NULL) + { + DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); + } + else + { + if (bytes) + { + *bytes = sa->curlft.bytes; + } + if (packets) + { + *packets = sa->curlft.packets; + } + if (time) + { /* curlft contains an "use" time, but that contains a timestamp + * of the first use, not the last. Last use time must be queried + * on the policy on Linux */ + *time = 0; + } + status = SUCCESS; + } + memwipe(out, len); + free(out); + return status; +} + +METHOD(kernel_ipsec_t, del_sa, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct xfrm_usersa_id *sa_id; + + /* if IPComp was used, we first delete the additional IPComp SA */ + if (cpi) + { + del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark); + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%08x)", + ntohl(spi), mark.value, mark.mask); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = XFRM_MSG_DELSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)); + + sa_id = NLMSG_DATA(hdr); + host2xfrm(dst, &sa_id->daddr); + sa_id->spi = spi; + sa_id->proto = protocol; + sa_id->family = dst->get_family(dst); + + if (!add_mark(hdr, sizeof(request), mark)) + { + return FAILED; + } + + switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr)) + { + case SUCCESS: + DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%08x)", + ntohl(spi), mark.value, mark.mask); + return SUCCESS; + case NOT_FOUND: + return NOT_FOUND; + default: + if (mark.value) + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x " + "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", + ntohl(spi)); + } + return FAILED; + } +} + +METHOD(kernel_ipsec_t, update_sa, status_t, + private_kernel_netlink_ipsec_t *this, u_int32_t spi, u_int8_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, + bool old_encap, bool new_encap, mark_t mark) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out = NULL; + struct xfrm_usersa_id *sa_id; + struct xfrm_usersa_info *out_sa = NULL, *sa; + size_t len; + struct rtattr *rta; + size_t rtasize; + struct xfrm_encap_tmpl* tmpl = NULL; + struct xfrm_replay_state *replay = NULL; + struct xfrm_replay_state_esn *replay_esn = NULL; + struct xfrm_lifetime_cur *lifetime = NULL; + u_int32_t replay_esn_len = 0; + status_t status = FAILED; + + /* if IPComp is used, we first update the IPComp SA */ + if (cpi) + { + update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0, + src, dst, new_src, new_dst, FALSE, FALSE, mark); + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi)); + + /* query the existing SA first */ + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_GETSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)); + + sa_id = NLMSG_DATA(hdr); + host2xfrm(dst, &sa_id->daddr); + sa_id->spi = spi; + sa_id->proto = protocol; + sa_id->family = dst->get_family(dst); + + if (!add_mark(hdr, sizeof(request), mark)) + { + return FAILED; + } + + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWSA: + { + out_sa = NLMSG_DATA(hdr); + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + DBG1(DBG_KNL, "querying SAD entry failed: %s (%d)", + strerror(-err->error), -err->error); + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + } + if (out_sa == NULL) + { + DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); + goto failed; + } + + get_replay_state(this, spi, protocol, dst, mark, &replay_esn, + &replay_esn_len, &replay, &lifetime); + + /* delete the old SA (without affecting the IPComp SA) */ + if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS) + { + DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", + ntohl(spi)); + goto failed; + } + + DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H", + ntohl(spi), src, dst, new_src, new_dst); + /* copy over the SA from out to request */ + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = XFRM_MSG_NEWSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)); + sa = NLMSG_DATA(hdr); + memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info)); + sa->family = new_dst->get_family(new_dst); + + if (!src->ip_equals(src, new_src)) + { + host2xfrm(new_src, &sa->saddr); + } + if (!dst->ip_equals(dst, new_dst)) + { + host2xfrm(new_dst, &sa->id.daddr); + } + + rta = XFRM_RTA(out, struct xfrm_usersa_info); + rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info); + while (RTA_OK(rta, rtasize)) + { + /* copy all attributes, but not XFRMA_ENCAP if we are disabling it */ + if (rta->rta_type != XFRMA_ENCAP || new_encap) + { + if (rta->rta_type == XFRMA_ENCAP) + { /* update encap tmpl */ + tmpl = RTA_DATA(rta); + tmpl->encap_sport = ntohs(new_src->get_port(new_src)); + tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); + } + netlink_add_attribute(hdr, rta->rta_type, + chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), + sizeof(request)); + } + rta = RTA_NEXT(rta, rtasize); + } + + if (tmpl == NULL && new_encap) + { /* add tmpl if we are enabling it */ + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl)); + if (!tmpl) + { + goto failed; + } + tmpl->encap_type = UDP_ENCAP_ESPINUDP; + tmpl->encap_sport = ntohs(new_src->get_port(new_src)); + tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); + memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t)); + } + + if (replay_esn) + { + struct xfrm_replay_state_esn *state; + + state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL, + replay_esn_len); + if (!state) + { + goto failed; + } + memcpy(state, replay_esn, replay_esn_len); + } + else if (replay) + { + struct xfrm_replay_state *state; + + state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL, + sizeof(*state)); + if (!state) + { + goto failed; + } + memcpy(state, replay, sizeof(*state)); + } + else + { + DBG1(DBG_KNL, "unable to copy replay state from old SAD entry with " + "SPI %.8x", ntohl(spi)); + } + if (lifetime) + { + struct xfrm_lifetime_cur *state; + + state = netlink_reserve(hdr, sizeof(request), XFRMA_LTIME_VAL, + sizeof(*state)); + if (!state) + { + goto failed; + } + memcpy(state, lifetime, sizeof(*state)); + } + else + { + DBG1(DBG_KNL, "unable to copy usage stats from old SAD entry with " + "SPI %.8x", ntohl(spi)); + } + + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) + { + DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); + goto failed; + } + + status = SUCCESS; +failed: + free(replay); + free(replay_esn); + free(lifetime); + memwipe(out, len); + memwipe(&request, sizeof(request)); + free(out); + + return status; +} + +METHOD(kernel_ipsec_t, flush_sas, status_t, + private_kernel_netlink_ipsec_t *this) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct xfrm_usersa_flush *flush; + struct { + u_int8_t proto; + char *name; + } protos[] = { + { IPPROTO_AH, "AH" }, + { IPPROTO_ESP, "ESP" }, + { IPPROTO_COMP, "IPComp" }, + }; + int i; + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = XFRM_MSG_FLUSHSA; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)); + + flush = NLMSG_DATA(hdr); + + for (i = 0; i < countof(protos); i++) + { + DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name); + + flush->proto = protos[i].proto; + + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) + { + DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name); + return FAILED; + } + } + return SUCCESS; +} + +/** + * Add or update a policy in the kernel. + * + * Note: The mutex has to be locked when entering this function + * and is unlocked here in any case. + */ +static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, + policy_entry_t *policy, policy_sa_t *mapping, bool update) +{ + netlink_buf_t request; + policy_entry_t clone; + ipsec_sa_t *ipsec = mapping->sa; + struct xfrm_userpolicy_info *policy_info; + struct nlmsghdr *hdr; + status_t status; + int i; + + /* clone the policy so we are able to check it out again later */ + memcpy(&clone, policy, sizeof(policy_entry_t)); + + memset(&request, 0, sizeof(request)); + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = update ? XFRM_MSG_UPDPOLICY : XFRM_MSG_NEWPOLICY; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)); + + policy_info = NLMSG_DATA(hdr); + policy_info->sel = policy->sel; + policy_info->dir = policy->direction; + + /* calculate priority based on selector size, small size = high prio */ + policy_info->priority = mapping->priority; + policy_info->action = mapping->type != POLICY_DROP ? XFRM_POLICY_ALLOW + : XFRM_POLICY_BLOCK; + policy_info->share = XFRM_SHARE_ANY; + + /* policies don't expire */ + policy_info->lft.soft_byte_limit = XFRM_INF; + policy_info->lft.soft_packet_limit = XFRM_INF; + policy_info->lft.hard_byte_limit = XFRM_INF; + policy_info->lft.hard_packet_limit = XFRM_INF; + policy_info->lft.soft_add_expires_seconds = 0; + policy_info->lft.hard_add_expires_seconds = 0; + policy_info->lft.soft_use_expires_seconds = 0; + policy_info->lft.hard_use_expires_seconds = 0; + + if (mapping->type == POLICY_IPSEC) + { + struct xfrm_user_tmpl *tmpl; + struct { + u_int8_t proto; + bool use; + } protos[] = { + { IPPROTO_COMP, ipsec->cfg.ipcomp.transform != IPCOMP_NONE }, + { IPPROTO_ESP, ipsec->cfg.esp.use }, + { IPPROTO_AH, ipsec->cfg.ah.use }, + }; + ipsec_mode_t proto_mode = ipsec->cfg.mode; + int count = 0; + + for (i = 0; i < countof(protos); i++) + { + if (protos[i].use) + { + count++; + } + } + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL, + count * sizeof(*tmpl)); + if (!tmpl) + { + this->mutex->unlock(this->mutex); + return FAILED; + } + + for (i = 0; i < countof(protos); i++) + { + if (!protos[i].use) + { + continue; + } + tmpl->reqid = ipsec->cfg.reqid; + tmpl->id.proto = protos[i].proto; + tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; + tmpl->mode = mode2kernel(proto_mode); + tmpl->optional = protos[i].proto == IPPROTO_COMP && + policy->direction != POLICY_OUT; + tmpl->family = ipsec->src->get_family(ipsec->src); + + if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET) + { /* only for tunnel mode */ + host2xfrm(ipsec->src, &tmpl->saddr); + host2xfrm(ipsec->dst, &tmpl->id.daddr); + } + + tmpl++; + + /* use transport mode for other SAs */ + proto_mode = MODE_TRANSPORT; + } + } + + if (!add_mark(hdr, sizeof(request), ipsec->mark)) + { + this->mutex->unlock(this->mutex); + return FAILED; + } + this->mutex->unlock(this->mutex); + + status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr); + if (status == ALREADY_DONE && !update) + { + DBG1(DBG_KNL, "policy already exists, try to update it"); + hdr->nlmsg_type = XFRM_MSG_UPDPOLICY; + status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr); + } + if (status != SUCCESS) + { + return FAILED; + } + + /* find the policy again */ + this->mutex->lock(this->mutex); + policy = this->policies->get(this->policies, &clone); + if (!policy || + policy->used_by->find_first(policy->used_by, + NULL, (void**)&mapping) != SUCCESS) + { /* policy or mapping is already gone, ignore */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + + /* install a route, if: + * - this is a forward policy (to just get one for each child) + * - we are in tunnel/BEET mode or install a bypass policy + * - routing is not disabled via strongswan.conf + */ + if (policy->direction == POLICY_FWD && this->install_routes && + (mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT)) + { + policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping; + route_entry_t *route; + host_t *iface; + + INIT(route, + .prefixlen = policy->sel.prefixlen_s, + ); + + if (charon->kernel->get_address_by_ts(charon->kernel, fwd->dst_ts, + &route->src_ip, NULL) == SUCCESS) + { + /* get the nexthop to src (src as we are in POLICY_FWD) */ + if (!ipsec->src->is_anyaddr(ipsec->src)) + { + route->gateway = charon->kernel->get_nexthop(charon->kernel, + ipsec->src, -1, ipsec->dst); + } + else + { /* for shunt policies */ + iface = xfrm2host(policy->sel.family, &policy->sel.saddr, 0); + route->gateway = charon->kernel->get_nexthop(charon->kernel, + iface, policy->sel.prefixlen_s, + route->src_ip); + iface->destroy(iface); + } + route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16); + memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len); + + /* get the interface to install the route for. If we have a local + * address, use it. Otherwise (for shunt policies) use the + * routes source address. */ + iface = ipsec->dst; + if (iface->is_anyaddr(iface)) + { + iface = route->src_ip; + } + /* install route via outgoing interface */ + if (!charon->kernel->get_interface(charon->kernel, iface, + &route->if_name)) + { + this->mutex->unlock(this->mutex); + route_entry_destroy(route); + return SUCCESS; + } + + if (policy->route) + { + route_entry_t *old = policy->route; + if (route_entry_equals(old, route)) + { + this->mutex->unlock(this->mutex); + route_entry_destroy(route); + return SUCCESS; + } + /* uninstall previously installed route */ + if (charon->kernel->del_route(charon->kernel, old->dst_net, + old->prefixlen, old->gateway, + old->src_ip, old->if_name) != SUCCESS) + { + DBG1(DBG_KNL, "error uninstalling route installed with " + "policy %R === %R %N", fwd->src_ts, + fwd->dst_ts, policy_dir_names, + policy->direction); + } + route_entry_destroy(old); + policy->route = NULL; + } + + DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", + fwd->src_ts, route->gateway, route->src_ip, route->if_name); + switch (charon->kernel->add_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name)) + { + default: + DBG1(DBG_KNL, "unable to install source route for %H", + route->src_ip); + /* FALL */ + case ALREADY_DONE: + /* route exists, do not uninstall */ + route_entry_destroy(route); + break; + case SUCCESS: + /* cache the installed route */ + policy->route = route; + break; + } + } + else + { + free(route); + } + } + this->mutex->unlock(this->mutex); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, add_policy, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) +{ + policy_entry_t *policy, *current; + policy_sa_t *assigned_sa, *current_sa; + enumerator_t *enumerator; + bool found = FALSE, update = TRUE; + + /* create a policy */ + INIT(policy, + .sel = ts2selector(src_ts, dst_ts), + .mark = mark.value & mark.mask, + .direction = direction, + .reqid = sa->reqid, + ); + + /* find the policy, which matches EXACTLY */ + this->mutex->lock(this->mutex); + current = this->policies->get(this->policies, policy); + if (current) + { + if (current->reqid && sa->reqid && current->reqid != sa->reqid) + { + DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark " + "%u/0x%08x) for reqid %u, the same policy for reqid %u exists", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask, sa->reqid, current->reqid); + policy_entry_destroy(this, policy); + this->mutex->unlock(this->mutex); + return INVALID_STATE; + } + /* use existing policy */ + DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%08x) " + "already exists, increasing refcount", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + policy_entry_destroy(this, policy); + policy = current; + found = TRUE; + } + else + { /* use the new one, if we have no such policy */ + policy->used_by = linked_list_create(); + this->policies->put(this->policies, policy, policy); + } + + /* cache the assigned IPsec SA */ + assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts, + dst_ts, mark, sa); + assigned_sa->priority = get_priority(policy, priority); + + /* insert the SA according to its priority */ + enumerator = policy->used_by->create_enumerator(policy->used_by); + while (enumerator->enumerate(enumerator, (void**)¤t_sa)) + { + if (current_sa->priority >= assigned_sa->priority) + { + break; + } + update = FALSE; + } + policy->used_by->insert_before(policy->used_by, enumerator, + assigned_sa); + enumerator->destroy(enumerator); + + if (!update) + { /* we don't update the policy if the priority is lower than that of + * the currently installed one */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + + if (this->policy_update) + { + found = TRUE; + } + + DBG2(DBG_KNL, "%s policy %R === %R %N (mark %u/0x%08x)", + found ? "updating" : "adding", src_ts, dst_ts, + policy_dir_names, direction, mark.value, mark.mask); + + if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS) + { + DBG1(DBG_KNL, "unable to %s policy %R === %R %N", + found ? "update" : "add", src_ts, dst_ts, + policy_dir_names, direction); + return FAILED; + } + return SUCCESS; +} + +METHOD(kernel_ipsec_t, query_policy, status_t, + private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + time_t *use_time) +{ + netlink_buf_t request; + struct nlmsghdr *out = NULL, *hdr; + struct xfrm_userpolicy_id *policy_id; + struct xfrm_userpolicy_info *policy = NULL; + size_t len; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%08x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_GETPOLICY; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)); + + policy_id = NLMSG_DATA(hdr); + policy_id->sel = ts2selector(src_ts, dst_ts); + policy_id->dir = direction; + + if (!add_mark(hdr, sizeof(request), mark)) + { + return FAILED; + } + + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWPOLICY: + { + policy = NLMSG_DATA(hdr); + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + DBG1(DBG_KNL, "querying policy failed: %s (%d)", + strerror(-err->error), -err->error); + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + } + + if (policy == NULL) + { + DBG2(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + free(out); + return FAILED; + } + + if (policy->curlft.use_time) + { + /* we need the monotonic time, but the kernel returns system time. */ + *use_time = time_monotonic(NULL) - (time(NULL) - policy->curlft.use_time); + } + else + { + *use_time = 0; + } + + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, del_policy, status_t, + private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t prio) +{ + policy_entry_t *current, policy; + enumerator_t *enumerator; + policy_sa_t *mapping; + netlink_buf_t request; + struct nlmsghdr *hdr; + struct xfrm_userpolicy_id *policy_id; + bool is_installed = TRUE; + u_int32_t priority; + ipsec_sa_t assigned_sa = { + .src = src, + .dst = dst, + .mark = mark, + .cfg = *sa, + }; + + DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%08x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + + /* create a policy */ + memset(&policy, 0, sizeof(policy_entry_t)); + policy.sel = ts2selector(src_ts, dst_ts); + policy.mark = mark.value & mark.mask; + policy.direction = direction; + + /* find the policy */ + this->mutex->lock(this->mutex); + current = this->policies->get(this->policies, &policy); + if (!current) + { + if (mark.value) + { + DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%08x) " + "failed, not found", src_ts, dst_ts, policy_dir_names, + direction, mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", + src_ts, dst_ts, policy_dir_names, direction); + } + this->mutex->unlock(this->mutex); + return NOT_FOUND; + } + + /* remove mapping to SA by reqid and priority */ + priority = get_priority(current, prio); + enumerator = current->used_by->create_enumerator(current->used_by); + while (enumerator->enumerate(enumerator, (void**)&mapping)) + { + if (priority == mapping->priority && type == mapping->type && + ipsec_sa_equals(mapping->sa, &assigned_sa)) + { + current->used_by->remove_at(current->used_by, enumerator); + policy_sa_destroy(mapping, &direction, this); + break; + } + is_installed = FALSE; + } + enumerator->destroy(enumerator); + + if (current->used_by->get_count(current->used_by) > 0) + { /* policy is used by more SAs, keep in kernel */ + DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed"); + if (!is_installed) + { /* no need to update as the policy was not installed for this SA */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + + DBG2(DBG_KNL, "updating policy %R === %R %N (mark %u/0x%08x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + + current->used_by->get_first(current->used_by, (void**)&mapping); + if (add_policy_internal(this, current, mapping, TRUE) != SUCCESS) + { + DBG1(DBG_KNL, "unable to update policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + return FAILED; + } + return SUCCESS; + } + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = XFRM_MSG_DELPOLICY; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)); + + policy_id = NLMSG_DATA(hdr); + policy_id->sel = current->sel; + policy_id->dir = direction; + + if (!add_mark(hdr, sizeof(request), mark)) + { + this->mutex->unlock(this->mutex); + return FAILED; + } + + if (current->route) + { + route_entry_t *route = current->route; + if (charon->kernel->del_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name) != SUCCESS) + { + DBG1(DBG_KNL, "error uninstalling route installed with " + "policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + } + } + + this->policies->remove(this->policies, current); + policy_entry_destroy(this, current); + this->mutex->unlock(this->mutex); + + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) + { + if (mark.value) + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N " + "(mark %u/0x%08x)", src_ts, dst_ts, policy_dir_names, + direction, mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + } + return FAILED; + } + return SUCCESS; +} + +METHOD(kernel_ipsec_t, flush_policies, status_t, + private_kernel_netlink_ipsec_t *this) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "flushing all policies from SPD"); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = XFRM_MSG_FLUSHPOLICY; + hdr->nlmsg_len = NLMSG_LENGTH(0); /* no data associated */ + + /* by adding an rtattr of type XFRMA_POLICY_TYPE we could restrict this + * to main or sub policies (default is main) */ + + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) + { + DBG1(DBG_KNL, "unable to flush SPD entries"); + return FAILED; + } + return SUCCESS; +} + +/** + * Bypass socket using a per-socket policy + */ +static bool add_socket_bypass(private_kernel_netlink_ipsec_t *this, + int fd, int family) +{ + struct xfrm_userpolicy_info policy; + u_int sol, ipsec_policy; + + switch (family) + { + case AF_INET: + sol = SOL_IP; + ipsec_policy = IP_XFRM_POLICY; + break; + case AF_INET6: + sol = SOL_IPV6; + ipsec_policy = IPV6_XFRM_POLICY; + break; + default: + return FALSE; + } + + memset(&policy, 0, sizeof(policy)); + policy.action = XFRM_POLICY_ALLOW; + policy.sel.family = family; + + policy.dir = XFRM_POLICY_OUT; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + policy.dir = XFRM_POLICY_IN; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + return TRUE; +} + +/** + * Port based IKE bypass policy + */ +typedef struct { + /** address family */ + int family; + /** layer 4 protocol */ + int proto; + /** port number, network order */ + u_int16_t port; +} bypass_t; + +/** + * Add or remove a bypass policy from/to kernel + */ +static bool manage_bypass(private_kernel_netlink_ipsec_t *this, + int type, policy_dir_t dir, bypass_t *bypass) +{ + netlink_buf_t request; + struct xfrm_selector *sel; + struct nlmsghdr *hdr; + + memset(&request, 0, sizeof(request)); + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = type; + + if (type == XFRM_MSG_NEWPOLICY) + { + struct xfrm_userpolicy_info *policy; + + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)); + + policy = NLMSG_DATA(hdr); + policy->dir = dir; + policy->priority = 32; + policy->action = XFRM_POLICY_ALLOW; + policy->share = XFRM_SHARE_ANY; + + policy->lft.soft_byte_limit = XFRM_INF; + policy->lft.soft_packet_limit = XFRM_INF; + policy->lft.hard_byte_limit = XFRM_INF; + policy->lft.hard_packet_limit = XFRM_INF; + + sel = &policy->sel; + } + else /* XFRM_MSG_DELPOLICY */ + { + struct xfrm_userpolicy_id *policy; + + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)); + + policy = NLMSG_DATA(hdr); + policy->dir = dir; + + sel = &policy->sel; + } + + sel->family = bypass->family; + sel->proto = bypass->proto; + if (dir == POLICY_IN) + { + sel->dport = bypass->port; + sel->dport_mask = 0xffff; + } + else + { + sel->sport = bypass->port; + sel->sport_mask = 0xffff; + } + return this->socket_xfrm->send_ack(this->socket_xfrm, hdr) == SUCCESS; +} + +/** + * Bypass socket using a port-based bypass policy + */ +static bool add_port_bypass(private_kernel_netlink_ipsec_t *this, + int fd, int family) +{ + union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; + } saddr; + socklen_t len; + bypass_t bypass = { + .family = family, + }; + + len = sizeof(saddr); + if (getsockname(fd, &saddr.sa, &len) != 0) + { + return FALSE; + } +#ifdef SO_PROTOCOL /* since 2.6.32 */ + len = sizeof(bypass.proto); + if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &bypass.proto, &len) != 0) +#endif + { /* assume UDP if SO_PROTOCOL not supported */ + bypass.proto = IPPROTO_UDP; + } + switch (family) + { + case AF_INET: + bypass.port = saddr.in.sin_port; + break; + case AF_INET6: + bypass.port = saddr.in6.sin6_port; + break; + default: + return FALSE; + } + + if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_IN, &bypass)) + { + return FALSE; + } + if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_OUT, &bypass)) + { + manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, &bypass); + return FALSE; + } + array_insert(this->bypass, ARRAY_TAIL, &bypass); + + return TRUE; +} + +/** + * Remove installed port based bypass policy + */ +static void remove_port_bypass(bypass_t *bypass, int idx, + private_kernel_netlink_ipsec_t *this) +{ + manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_OUT, bypass); + manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, bypass); +} + +METHOD(kernel_ipsec_t, bypass_socket, bool, + private_kernel_netlink_ipsec_t *this, int fd, int family) +{ + if (lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.port_bypass", FALSE, lib->ns)) + { + return add_port_bypass(this, fd, family); + } + return add_socket_bypass(this, fd, family); +} + +METHOD(kernel_ipsec_t, enable_udp_decap, bool, + private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port) +{ + int type = UDP_ENCAP_ESPINUDP; + + if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + { + DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno)); + return FALSE; + } + return TRUE; +} + +METHOD(kernel_ipsec_t, destroy, void, + private_kernel_netlink_ipsec_t *this) +{ + enumerator_t *enumerator; + policy_entry_t *policy; + + array_destroy_function(this->bypass, + (array_callback_t)remove_port_bypass, this); + if (this->socket_xfrm_events > 0) + { + lib->watcher->remove(lib->watcher, this->socket_xfrm_events); + close(this->socket_xfrm_events); + } + DESTROY_IF(this->socket_xfrm); + enumerator = this->policies->create_enumerator(this->policies); + while (enumerator->enumerate(enumerator, &policy, &policy)) + { + policy_entry_destroy(this, policy); + } + enumerator->destroy(enumerator); + this->policies->destroy(this->policies); + this->sas->destroy(this->sas); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * Described in header. + */ +kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() +{ + private_kernel_netlink_ipsec_t *this; + bool register_for_events = TRUE; + FILE *f; + + INIT(this, + .public = { + .interface = { + .get_features = _get_features, + .get_spi = _get_spi, + .get_cpi = _get_cpi, + .add_sa = _add_sa, + .update_sa = _update_sa, + .query_sa = _query_sa, + .del_sa = _del_sa, + .flush_sas = _flush_sas, + .add_policy = _add_policy, + .query_policy = _query_policy, + .del_policy = _del_policy, + .flush_policies = _flush_policies, + .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, + .destroy = _destroy, + }, + }, + .policies = hashtable_create((hashtable_hash_t)policy_hash, + (hashtable_equals_t)policy_equals, 32), + .sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash, + (hashtable_equals_t)ipsec_sa_equals, 32), + .bypass = array_create(sizeof(bypass_t), 0), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .policy_update = lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns), + .install_routes = lib->settings->get_bool(lib->settings, + "%s.install_routes", TRUE, lib->ns), + .proto_port_transport = lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.set_proto_port_transport_sa", + FALSE, lib->ns), + ); + + if (streq(lib->ns, "starter")) + { /* starter has no threads, so we do not register for kernel events */ + register_for_events = FALSE; + } + + f = fopen("/proc/sys/net/core/xfrm_acq_expires", "w"); + if (f) + { + fprintf(f, "%u", lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.xfrm_acq_expires", + DEFAULT_ACQUIRE_LIFETIME, lib->ns)); + fclose(f); + } + + this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names, + lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns)); + if (!this->socket_xfrm) + { + destroy(this); + return NULL; + } + + if (register_for_events) + { + struct sockaddr_nl addr; + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + + /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */ + this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM); + if (this->socket_xfrm_events <= 0) + { + DBG1(DBG_KNL, "unable to create XFRM event socket"); + destroy(this); + return NULL; + } + addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) | + XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING); + if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr))) + { + DBG1(DBG_KNL, "unable to bind XFRM event socket"); + destroy(this); + return NULL; + } + lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ, + (watcher_cb_t)receive_events, this); + } + + return &this->public; +} diff --git a/src/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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..f4394a14f --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c @@ -0,0 +1,2686 @@ +/* + * Copyright (C) 2008-2014 Tobias Brunner + * Copyright (C) 2005-2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_FIB_RULES_H +#include +#endif + +#include "kernel_netlink_net.h" +#include "kernel_netlink_shared.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** delay before firing roam events (ms) */ +#define ROAM_DELAY 100 + +/** delay before reinstalling routes (ms) */ +#define ROUTE_DELAY 100 + +/** maximum recursion when searching for addresses in get_route() */ +#define MAX_ROUTE_RECURSION 2 + +#ifndef ROUTING_TABLE +#define ROUTING_TABLE 0 +#endif + +#ifndef ROUTING_TABLE_PRIO +#define ROUTING_TABLE_PRIO 0 +#endif + +ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE, + "RTM_NEWLINK", + "RTM_DELLINK", + "RTM_GETLINK", + "RTM_SETLINK", + "RTM_NEWADDR", + "RTM_DELADDR", + "RTM_GETADDR", + "31", + "RTM_NEWROUTE", + "RTM_DELROUTE", + "RTM_GETROUTE", + "35", + "RTM_NEWNEIGH", + "RTM_DELNEIGH", + "RTM_GETNEIGH", + "RTM_NEWRULE", + "RTM_DELRULE", + "RTM_GETRULE", +); + +typedef struct addr_entry_t addr_entry_t; + +/** + * IP address in an iface_entry_t + */ +struct addr_entry_t { + + /** the ip address */ + host_t *ip; + + /** address flags */ + u_char flags; + + /** scope of the address */ + u_char scope; + + /** number of times this IP is used, if virtual (i.e. managed by us) */ + u_int refcount; + + /** TRUE once it is installed, if virtual */ + bool installed; +}; + +/** + * destroy a addr_entry_t object + */ +static void addr_entry_destroy(addr_entry_t *this) +{ + this->ip->destroy(this->ip); + free(this); +} + +typedef struct iface_entry_t iface_entry_t; + +/** + * A network interface on this system, containing addr_entry_t's + */ +struct iface_entry_t { + + /** interface index */ + int ifindex; + + /** name of the interface */ + char ifname[IFNAMSIZ]; + + /** interface flags, as in netdevice(7) SIOCGIFFLAGS */ + u_int flags; + + /** list of addresses as host_t */ + linked_list_t *addrs; + + /** TRUE if usable by config */ + bool usable; +}; + +/** + * destroy an interface entry + */ +static void iface_entry_destroy(iface_entry_t *this) +{ + this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy); + free(this); +} + +/** + * find an interface entry by index + */ +static bool iface_entry_by_index(iface_entry_t *this, int *ifindex) +{ + return this->ifindex == *ifindex; +} + +/** + * find an interface entry by name + */ +static bool iface_entry_by_name(iface_entry_t *this, char *ifname) +{ + return streq(this->ifname, ifname); +} + +/** + * check if an interface is up + */ +static inline bool iface_entry_up(iface_entry_t *iface) +{ + return (iface->flags & IFF_UP) == IFF_UP; +} + +/** + * check if an interface is up and usable + */ +static inline bool iface_entry_up_and_usable(iface_entry_t *iface) +{ + return iface->usable && iface_entry_up(iface); +} + +typedef struct addr_map_entry_t addr_map_entry_t; + +/** + * Entry that maps an IP address to an interface entry + */ +struct addr_map_entry_t { + /** The IP address */ + host_t *ip; + + /** The address entry for this IP address */ + addr_entry_t *addr; + + /** The interface this address is installed on */ + iface_entry_t *iface; +}; + +/** + * Hash a addr_map_entry_t object, all entries with the same IP address + * are stored in the same bucket + */ +static u_int addr_map_entry_hash(addr_map_entry_t *this) +{ + return chunk_hash(this->ip->get_address(this->ip)); +} + +/** + * Compare two addr_map_entry_t objects, two entries are equal if they are + * installed on the same interface + */ +static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return a->iface->ifindex == b->iface->ifindex && + a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed on + * an up and usable interface + */ +static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a, + addr_map_entry_t *b) +{ + return iface_entry_up_and_usable(b->iface) && + a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed on + * any active local interface + */ +static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed on + * any local interface + */ +static bool addr_map_entry_match(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return a->ip->ip_equals(a->ip, b->ip); +} + +typedef struct route_entry_t route_entry_t; + +/** + * Installed routing entry + */ +struct route_entry_t { + /** Name of the interface the route is bound to */ + char *if_name; + + /** Source ip of the route */ + host_t *src_ip; + + /** Gateway for this route */ + host_t *gateway; + + /** Destination net */ + chunk_t dst_net; + + /** Destination net prefixlen */ + u_int8_t prefixlen; +}; + +/** + * Clone a route_entry_t object. + */ +static route_entry_t *route_entry_clone(route_entry_t *this) +{ + route_entry_t *route; + + INIT(route, + .if_name = strdup(this->if_name), + .src_ip = this->src_ip->clone(this->src_ip), + .gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL, + .dst_net = chunk_clone(this->dst_net), + .prefixlen = this->prefixlen, + ); + return route; +} + +/** + * Destroy a route_entry_t object + */ +static void route_entry_destroy(route_entry_t *this) +{ + free(this->if_name); + DESTROY_IF(this->src_ip); + DESTROY_IF(this->gateway); + chunk_free(&this->dst_net); + free(this); +} + +/** + * Hash a route_entry_t object + */ +static u_int route_entry_hash(route_entry_t *this) +{ + return chunk_hash_inc(chunk_from_thing(this->prefixlen), + chunk_hash(this->dst_net)); +} + +/** + * Compare two route_entry_t objects + */ +static bool route_entry_equals(route_entry_t *a, route_entry_t *b) +{ + if (a->if_name && b->if_name && streq(a->if_name, b->if_name) && + a->src_ip->ip_equals(a->src_ip, b->src_ip) && + chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen) + { + return (!a->gateway && !b->gateway) || (a->gateway && b->gateway && + a->gateway->ip_equals(a->gateway, b->gateway)); + } + return FALSE; +} + +typedef struct net_change_t net_change_t; + +/** + * Queued network changes + */ +struct net_change_t { + /** Name of the interface that got activated (or an IP appeared on) */ + char *if_name; +}; + +/** + * Destroy a net_change_t object + */ +static void net_change_destroy(net_change_t *this) +{ + free(this->if_name); + free(this); +} + +/** + * Hash a net_change_t object + */ +static u_int net_change_hash(net_change_t *this) +{ + return chunk_hash(chunk_create(this->if_name, strlen(this->if_name))); +} + +/** + * Compare two net_change_t objects + */ +static bool net_change_equals(net_change_t *a, net_change_t *b) +{ + return streq(a->if_name, b->if_name); +} + +typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t; + +/** + * Private variables and functions of kernel_netlink_net class. + */ +struct private_kernel_netlink_net_t { + /** + * Public part of the kernel_netlink_net_t object. + */ + kernel_netlink_net_t public; + + /** + * lock to access various lists and maps + */ + rwlock_t *lock; + + /** + * condition variable to signal virtual IP add/removal + */ + rwlock_condvar_t *condvar; + + /** + * Cached list of interfaces and its addresses (iface_entry_t) + */ + linked_list_t *ifaces; + + /** + * Map for IP addresses to iface_entry_t objects (addr_map_entry_t) + */ + hashtable_t *addrs; + + /** + * Map for virtual IP addresses to iface_entry_t objects (addr_map_entry_t) + */ + hashtable_t *vips; + + /** + * netlink rt socket (routing) + */ + netlink_socket_t *socket; + + /** + * Netlink rt socket to receive address change events + */ + int socket_events; + + /** + * earliest time of the next roam event + */ + timeval_t next_roam; + + /** + * roam event due to address change + */ + bool roam_address; + + /** + * lock to check and update roam event time + */ + spinlock_t *roam_lock; + + /** + * routing table to install routes + */ + int routing_table; + + /** + * priority of used routing table + */ + int routing_table_prio; + + /** + * installed routes + */ + hashtable_t *routes; + + /** + * mutex for routes + */ + mutex_t *routes_lock; + + /** + * interface changes which may trigger route reinstallation + */ + hashtable_t *net_changes; + + /** + * mutex for route reinstallation triggers + */ + mutex_t *net_changes_lock; + + /** + * time of last route reinstallation + */ + timeval_t last_route_reinstall; + + /** + * whether to react to RTM_NEWROUTE or RTM_DELROUTE events + */ + bool process_route; + + /** + * whether to trigger roam events + */ + bool roam_events; + + /** + * whether to actually install virtual IPs + */ + bool install_virtual_ip; + + /** + * the name of the interface virtual IP addresses are installed on + */ + char *install_virtual_ip_on; + + /** + * whether preferred source addresses can be specified for IPv6 routes + */ + bool rta_prefsrc_for_ipv6; + + /** + * whether marks can be used in route lookups + */ + bool rta_mark; + + /** + * the mark excluded from the routing rule used for virtual IPs + */ + mark_t routing_mark; + + /** + * whether to prefer temporary IPv6 addresses over public ones + */ + bool prefer_temporary_addrs; + + /** + * list with routing tables to be excluded from route lookup + */ + linked_list_t *rt_exclude; + + /** + * MTU to set on installed routes + */ + u_int32_t mtu; + + /** + * MSS to set on installed routes + */ + u_int32_t mss; +}; + +/** + * Forward declaration + */ +static status_t manage_srcroute(private_kernel_netlink_net_t *this, + int nlmsg_type, int flags, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, + host_t *src_ip, char *if_name); + +/** + * Clear the queued network changes. + */ +static void net_changes_clear(private_kernel_netlink_net_t *this) +{ + enumerator_t *enumerator; + net_change_t *change; + + enumerator = this->net_changes->create_enumerator(this->net_changes); + while (enumerator->enumerate(enumerator, NULL, (void**)&change)) + { + this->net_changes->remove_at(this->net_changes, enumerator); + net_change_destroy(change); + } + enumerator->destroy(enumerator); +} + +/** + * Act upon queued network changes. + */ +static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this) +{ + enumerator_t *enumerator; + route_entry_t *route; + + this->net_changes_lock->lock(this->net_changes_lock); + this->routes_lock->lock(this->routes_lock); + + enumerator = this->routes->create_enumerator(this->routes); + while (enumerator->enumerate(enumerator, NULL, (void**)&route)) + { + net_change_t *change, lookup = { + .if_name = route->if_name, + }; + /* check if a change for the outgoing interface is queued */ + change = this->net_changes->get(this->net_changes, &lookup); + if (!change) + { /* in case src_ip is not on the outgoing interface */ + if (this->public.interface.get_interface(&this->public.interface, + route->src_ip, &lookup.if_name)) + { + if (!streq(lookup.if_name, route->if_name)) + { + change = this->net_changes->get(this->net_changes, &lookup); + } + free(lookup.if_name); + } + } + if (change) + { + manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, + route->dst_net, route->prefixlen, route->gateway, + route->src_ip, route->if_name); + } + } + enumerator->destroy(enumerator); + this->routes_lock->unlock(this->routes_lock); + + net_changes_clear(this); + this->net_changes_lock->unlock(this->net_changes_lock); + return JOB_REQUEUE_NONE; +} + +/** + * Queue route reinstallation caused by network changes for a given interface. + * + * The route reinstallation is delayed for a while and only done once for + * several calls during this delay, in order to avoid doing it too often. + * The interface name is freed. + */ +static void queue_route_reinstall(private_kernel_netlink_net_t *this, + char *if_name) +{ + net_change_t *update, *found; + timeval_t now; + job_t *job; + + INIT(update, + .if_name = if_name + ); + + this->net_changes_lock->lock(this->net_changes_lock); + found = this->net_changes->put(this->net_changes, update, update); + if (found) + { + net_change_destroy(found); + } + time_monotonic(&now); + if (timercmp(&now, &this->last_route_reinstall, >)) + { + timeval_add_ms(&now, ROUTE_DELAY); + this->last_route_reinstall = now; + + job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes, + this, NULL, NULL); + lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY); + } + this->net_changes_lock->unlock(this->net_changes_lock); +} + +/** + * check if the given IP is known as virtual IP and currently installed + * + * this function will also return TRUE if the virtual IP entry disappeared. + * in that case the returned entry will be NULL. + * + * this->lock must be held when calling this function + */ +static bool is_vip_installed_or_gone(private_kernel_netlink_net_t *this, + host_t *ip, addr_map_entry_t **entry) +{ + addr_map_entry_t lookup = { + .ip = ip, + }; + + *entry = this->vips->get_match(this->vips, &lookup, + (void*)addr_map_entry_match); + if (*entry == NULL) + { /* the virtual IP disappeared */ + return TRUE; + } + return (*entry)->addr->installed; +} + +/** + * check if the given IP is known as virtual IP + * + * this->lock must be held when calling this function + */ +static bool is_known_vip(private_kernel_netlink_net_t *this, host_t *ip) +{ + addr_map_entry_t lookup = { + .ip = ip, + }; + + return this->vips->get_match(this->vips, &lookup, + (void*)addr_map_entry_match) != NULL; +} + +/** + * Add an address map entry + */ +static void addr_map_entry_add(hashtable_t *map, addr_entry_t *addr, + iface_entry_t *iface) +{ + addr_map_entry_t *entry; + + INIT(entry, + .ip = addr->ip, + .addr = addr, + .iface = iface, + ); + entry = map->put(map, entry, entry); + free(entry); +} + +/** + * Remove an address map entry + */ +static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr, + iface_entry_t *iface) +{ + addr_map_entry_t *entry, lookup = { + .ip = addr->ip, + .addr = addr, + .iface = iface, + }; + + entry = map->remove(map, &lookup); + free(entry); +} + +/** + * Determine the type or scope of the given unicast IP address. This is not + * the same thing returned in rtm_scope/ifa_scope. + * + * We use return values as defined in RFC 6724 (referring to RFC 4291). + */ +static u_char get_scope(host_t *ip) +{ + chunk_t addr; + + addr = ip->get_address(ip); + switch (addr.len) + { + case 4: + /* we use the mapping defined in RFC 6724, 3.2 */ + if (addr.ptr[0] == 127) + { /* link-local, same as the IPv6 loopback address */ + return 2; + } + if (addr.ptr[0] == 169 && addr.ptr[1] == 254) + { /* link-local */ + return 2; + } + break; + case 16: + if (IN6_IS_ADDR_LOOPBACK((struct in6_addr*)addr.ptr)) + { /* link-local, according to RFC 4291, 2.5.3 */ + return 2; + } + if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr.ptr)) + { + return 2; + } + if (IN6_IS_ADDR_SITELOCAL((struct in6_addr*)addr.ptr)) + { /* deprecated, according to RFC 4291, 2.5.7 */ + return 5; + } + break; + default: + break; + } + /* global */ + return 14; +} + +/** + * Returns the length of the common prefix in bits up to the length of a's + * prefix, defined by RFC 6724 as the portion of the address not including the + * interface ID, which is 64-bit for most unicast addresses (see RFC 4291). + */ +static u_char common_prefix(host_t *a, host_t *b) +{ + chunk_t aa, ba; + u_char byte, bits = 0, match; + + aa = a->get_address(a); + ba = b->get_address(b); + for (byte = 0; byte < 8; byte++) + { + if (aa.ptr[byte] != ba.ptr[byte]) + { + match = aa.ptr[byte] ^ ba.ptr[byte]; + for (bits = 8; match; match >>= 1) + { + bits--; + } + break; + } + } + return byte * 8 + bits; +} + +/** + * Compare two IP addresses and return TRUE if the second address is the better + * choice of the two to reach the destination. + * For IPv6 we approximately follow RFC 6724. + */ +static bool is_address_better(private_kernel_netlink_net_t *this, + addr_entry_t *a, addr_entry_t *b, host_t *d) +{ + u_char sa, sb, sd, pa, pb; + + /* rule 2: prefer appropriate scope */ + if (d) + { + sa = get_scope(a->ip); + sb = get_scope(b->ip); + sd = get_scope(d); + if (sa < sb) + { + return sa < sd; + } + else if (sb < sa) + { + return sb >= sd; + } + } + if (a->ip->get_family(a->ip) == AF_INET) + { /* stop here for IPv4, default to addresses found earlier */ + return FALSE; + } + /* rule 3: avoid deprecated addresses (RFC 4862) */ + if ((a->flags & IFA_F_DEPRECATED) != (b->flags & IFA_F_DEPRECATED)) + { + return a->flags & IFA_F_DEPRECATED; + } + /* rule 4 is not applicable as we don't know if an address is a home or + * care-of addresses. + * rule 5 does not apply as we only compare addresses from one interface + * rule 6 requires a policy table (optionally configurable) to match + * configurable labels + */ + /* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */ + if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY)) + { + if (this->prefer_temporary_addrs) + { + return b->flags & IFA_F_TEMPORARY; + } + return a->flags & IFA_F_TEMPORARY; + } + /* rule 8: use longest matching prefix */ + if (d) + { + pa = common_prefix(a->ip, d); + pb = common_prefix(b->ip, d); + if (pa != pb) + { + return pb > pa; + } + } + /* default to addresses found earlier */ + return FALSE; +} + +/** + * Get a non-virtual IP address on the given interface. + * + * If a candidate address is given, we first search for that address and if not + * found return the address as above. + * Returned host is a clone, has to be freed by caller. + * + * this->lock must be held when calling this function. + */ +static host_t *get_interface_address(private_kernel_netlink_net_t *this, + int ifindex, int family, host_t *dest, + host_t *candidate) +{ + iface_entry_t *iface; + enumerator_t *addrs; + addr_entry_t *addr, *best = NULL; + + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index, + (void**)&iface, &ifindex) == SUCCESS) + { + if (iface->usable) + { /* only use interfaces not excluded by config */ + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, &addr)) + { + if (addr->refcount || + addr->ip->get_family(addr->ip) != family) + { /* ignore virtual IP addresses and ensure family matches */ + continue; + } + if (candidate && candidate->ip_equals(candidate, addr->ip)) + { /* stop if we find the candidate */ + best = addr; + break; + } + else if (!best || is_address_better(this, best, addr, dest)) + { + best = addr; + } + } + addrs->destroy(addrs); + } + } + return best ? best->ip->clone(best->ip) : NULL; +} + +/** + * callback function that raises the delayed roam event + */ +static job_requeue_t roam_event(private_kernel_netlink_net_t *this) +{ + bool address; + + this->roam_lock->lock(this->roam_lock); + address = this->roam_address; + this->roam_address = FALSE; + this->roam_lock->unlock(this->roam_lock); + charon->kernel->roam(charon->kernel, address); + return JOB_REQUEUE_NONE; +} + +/** + * fire a roaming event. we delay it for a bit and fire only one event + * for multiple calls. otherwise we would create too many events. + */ +static void fire_roam_event(private_kernel_netlink_net_t *this, bool address) +{ + timeval_t now; + job_t *job; + + if (!this->roam_events) + { + return; + } + + time_monotonic(&now); + this->roam_lock->lock(this->roam_lock); + this->roam_address |= address; + if (!timercmp(&now, &this->next_roam, >)) + { + this->roam_lock->unlock(this->roam_lock); + return; + } + timeval_add_ms(&now, ROAM_DELAY); + this->next_roam = now; + this->roam_lock->unlock(this->roam_lock); + + job = (job_t*)callback_job_create((callback_job_cb_t)roam_event, + this, NULL, NULL); + lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY); +} + +/** + * check if an interface with a given index is up and usable + * + * this->lock must be locked when calling this function + */ +static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this, + int index) +{ + iface_entry_t *iface; + + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index, + (void**)&iface, &index) == SUCCESS) + { + return iface_entry_up_and_usable(iface); + } + return FALSE; +} + +/** + * unregister the current addr_entry_t from the hashtable it is stored in + * + * this->lock must be locked when calling this function + */ +static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface, + private_kernel_netlink_net_t *this) +{ + if (addr->refcount) + { + addr_map_entry_remove(this->vips, addr, iface); + this->condvar->broadcast(this->condvar); + return; + } + addr_map_entry_remove(this->addrs, addr, iface); +} + +/** + * process RTM_NEWLINK/RTM_DELLINK from kernel + */ +static void process_link(private_kernel_netlink_net_t *this, + struct nlmsghdr *hdr, bool event) +{ + struct ifinfomsg* msg = NLMSG_DATA(hdr); + struct rtattr *rta = IFLA_RTA(msg); + size_t rtasize = IFLA_PAYLOAD (hdr); + enumerator_t *enumerator; + iface_entry_t *current, *entry = NULL; + char *name = NULL; + bool update = FALSE, update_routes = FALSE; + + while (RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case IFLA_IFNAME: + name = RTA_DATA(rta); + break; + } + rta = RTA_NEXT(rta, rtasize); + } + if (!name) + { + name = "(unknown)"; + } + + this->lock->write_lock(this->lock); + switch (hdr->nlmsg_type) + { + case RTM_NEWLINK: + { + if (this->ifaces->find_first(this->ifaces, + (void*)iface_entry_by_index, (void**)&entry, + &msg->ifi_index) != SUCCESS) + { + INIT(entry, + .ifindex = msg->ifi_index, + .addrs = linked_list_create(), + .usable = charon->kernel->is_interface_usable( + charon->kernel, name), + ); + this->ifaces->insert_last(this->ifaces, entry); + } + strncpy(entry->ifname, name, IFNAMSIZ); + entry->ifname[IFNAMSIZ-1] = '\0'; + if (event && entry->usable) + { + if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP)) + { + update = update_routes = TRUE; + DBG1(DBG_KNL, "interface %s activated", name); + } + if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP)) + { + update = TRUE; + DBG1(DBG_KNL, "interface %s deactivated", name); + } + } + entry->flags = msg->ifi_flags; + break; + } + case RTM_DELLINK: + { + enumerator = this->ifaces->create_enumerator(this->ifaces); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->ifindex == msg->ifi_index) + { + if (event && current->usable) + { + update = TRUE; + DBG1(DBG_KNL, "interface %s deleted", current->ifname); + } + /* TODO: move virtual IPs installed on this interface to + * another interface? */ + this->ifaces->remove_at(this->ifaces, enumerator); + current->addrs->invoke_function(current->addrs, + (void*)addr_entry_unregister, current, this); + iface_entry_destroy(current); + break; + } + } + enumerator->destroy(enumerator); + break; + } + } + this->lock->unlock(this->lock); + + if (update_routes && event) + { + queue_route_reinstall(this, strdup(name)); + } + + if (update && event) + { + fire_roam_event(this, TRUE); + } +} + +/** + * process RTM_NEWADDR/RTM_DELADDR from kernel + */ +static void process_addr(private_kernel_netlink_net_t *this, + struct nlmsghdr *hdr, bool event) +{ + struct ifaddrmsg* msg = NLMSG_DATA(hdr); + struct rtattr *rta = IFA_RTA(msg); + size_t rtasize = IFA_PAYLOAD (hdr); + host_t *host = NULL; + iface_entry_t *iface; + chunk_t local = chunk_empty, address = chunk_empty; + char *route_ifname = NULL; + bool update = FALSE, found = FALSE, changed = FALSE; + + while (RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case IFA_LOCAL: + local.ptr = RTA_DATA(rta); + local.len = RTA_PAYLOAD(rta); + break; + case IFA_ADDRESS: + address.ptr = RTA_DATA(rta); + address.len = RTA_PAYLOAD(rta); + break; + } + rta = RTA_NEXT(rta, rtasize); + } + + /* For PPP interfaces, we need the IFA_LOCAL address, + * IFA_ADDRESS is the peers address. But IFA_LOCAL is + * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */ + if (local.ptr) + { + host = host_create_from_chunk(msg->ifa_family, local, 0); + } + else if (address.ptr) + { + host = host_create_from_chunk(msg->ifa_family, address, 0); + } + + if (host == NULL) + { /* bad family? */ + return; + } + + this->lock->write_lock(this->lock); + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index, + (void**)&iface, &msg->ifa_index) == SUCCESS) + { + addr_map_entry_t *entry, lookup = { + .ip = host, + .iface = iface, + }; + addr_entry_t *addr; + + entry = this->vips->get(this->vips, &lookup); + if (entry) + { + if (hdr->nlmsg_type == RTM_NEWADDR) + { /* mark as installed and signal waiting threads */ + entry->addr->installed = TRUE; + } + else + { /* the address was already marked as uninstalled */ + addr = entry->addr; + iface->addrs->remove(iface->addrs, addr, NULL); + addr_map_entry_remove(this->vips, addr, iface); + addr_entry_destroy(addr); + } + /* no roam events etc. for virtual IPs */ + this->condvar->broadcast(this->condvar); + this->lock->unlock(this->lock); + host->destroy(host); + return; + } + entry = this->addrs->get(this->addrs, &lookup); + if (entry) + { + if (hdr->nlmsg_type == RTM_DELADDR) + { + found = TRUE; + addr = entry->addr; + iface->addrs->remove(iface->addrs, addr, NULL); + if (iface->usable) + { + changed = TRUE; + DBG1(DBG_KNL, "%H disappeared from %s", host, + iface->ifname); + } + addr_map_entry_remove(this->addrs, addr, iface); + addr_entry_destroy(addr); + } + } + else + { + if (hdr->nlmsg_type == RTM_NEWADDR) + { + found = TRUE; + changed = TRUE; + route_ifname = strdup(iface->ifname); + INIT(addr, + .ip = host->clone(host), + .flags = msg->ifa_flags, + .scope = msg->ifa_scope, + ); + iface->addrs->insert_last(iface->addrs, addr); + addr_map_entry_add(this->addrs, addr, iface); + if (event && iface->usable) + { + DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); + } + } + } + if (found && (iface->flags & IFF_UP)) + { + update = TRUE; + } + if (!iface->usable) + { /* ignore events for interfaces excluded by config */ + update = changed = FALSE; + } + } + this->lock->unlock(this->lock); + + if (update && event && route_ifname) + { + queue_route_reinstall(this, route_ifname); + } + else + { + free(route_ifname); + } + host->destroy(host); + + /* send an update to all IKE_SAs */ + if (update && event && changed) + { + fire_roam_event(this, TRUE); + } +} + +/** + * process RTM_NEWROUTE and RTM_DELROUTE from kernel + */ +static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr) +{ + struct rtmsg* msg = NLMSG_DATA(hdr); + struct rtattr *rta = RTM_RTA(msg); + size_t rtasize = RTM_PAYLOAD(hdr); + u_int32_t rta_oif = 0; + host_t *host = NULL; + + /* ignore routes added by us or in the local routing table (local addrs) */ + if (msg->rtm_table && (msg->rtm_table == this->routing_table || + msg->rtm_table == RT_TABLE_LOCAL)) + { + return; + } + else if (msg->rtm_flags & RTM_F_CLONED) + { /* ignore cached routes, seem to be created a lot for IPv6 */ + return; + } + + while (RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case RTA_PREFSRC: + DESTROY_IF(host); + host = host_create_from_chunk(msg->rtm_family, + chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0); + break; + case RTA_OIF: + if (RTA_PAYLOAD(rta) == sizeof(rta_oif)) + { + rta_oif = *(u_int32_t*)RTA_DATA(rta); + } + break; + } + rta = RTA_NEXT(rta, rtasize); + } + this->lock->read_lock(this->lock); + if (rta_oif && !is_interface_up_and_usable(this, rta_oif)) + { /* ignore route changes for interfaces that are ignored or down */ + this->lock->unlock(this->lock); + DESTROY_IF(host); + return; + } + if (!host && rta_oif) + { + host = get_interface_address(this, rta_oif, msg->rtm_family, + NULL, NULL); + } + if (!host || is_known_vip(this, host)) + { /* ignore routes added for virtual IPs */ + this->lock->unlock(this->lock); + DESTROY_IF(host); + return; + } + this->lock->unlock(this->lock); + fire_roam_event(this, FALSE); + host->destroy(host); +} + +/** + * Receives events from kernel + */ +static bool receive_events(private_kernel_netlink_net_t *this, int fd, + watcher_event_t event) +{ + char response[1536]; + struct nlmsghdr *hdr = (struct nlmsghdr*)response; + struct sockaddr_nl addr; + socklen_t addr_len = sizeof(addr); + int len; + + len = recvfrom(this->socket_events, response, sizeof(response), + MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len); + if (len < 0) + { + switch (errno) + { + case EINTR: + /* interrupted, try again */ + return TRUE; + case EAGAIN: + /* no data ready, select again */ + return TRUE; + default: + DBG1(DBG_KNL, "unable to receive from rt event socket"); + sleep(1); + return TRUE; + } + } + + if (addr.nl_pid != 0) + { /* not from kernel. not interested, try another one */ + return TRUE; + } + + while (NLMSG_OK(hdr, len)) + { + /* looks good so far, dispatch netlink message */ + switch (hdr->nlmsg_type) + { + case RTM_NEWADDR: + case RTM_DELADDR: + process_addr(this, hdr, TRUE); + break; + case RTM_NEWLINK: + case RTM_DELLINK: + process_link(this, hdr, TRUE); + break; + case RTM_NEWROUTE: + case RTM_DELROUTE: + if (this->process_route) + { + process_route(this, hdr); + } + break; + default: + break; + } + hdr = NLMSG_NEXT(hdr, len); + } + return TRUE; +} + +/** enumerator over addresses */ +typedef struct { + private_kernel_netlink_net_t* this; + /** which addresses to enumerate */ + kernel_address_type_t which; +} address_enumerator_t; + +/** + * cleanup function for address enumerator + */ +static void address_enumerator_destroy(address_enumerator_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * filter for addresses + */ +static bool filter_addresses(address_enumerator_t *data, + addr_entry_t** in, host_t** out) +{ + if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->refcount) + { /* skip virtual interfaces added by us */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->refcount) + { /* address is regular, but not requested */ + return FALSE; + } + if ((*in)->scope >= RT_SCOPE_LINK) + { /* skip addresses with a unusable scope */ + return FALSE; + } + *out = (*in)->ip; + return TRUE; +} + +/** + * enumerator constructor for interfaces + */ +static enumerator_t *create_iface_enumerator(iface_entry_t *iface, + address_enumerator_t *data) +{ + return enumerator_create_filter( + iface->addrs->create_enumerator(iface->addrs), + (void*)filter_addresses, data, NULL); +} + +/** + * filter for interfaces + */ +static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, + iface_entry_t** out) +{ + if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable) + { /* skip interfaces excluded by config */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK)) + { /* ignore loopback devices */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP)) + { /* skip interfaces not up */ + return FALSE; + } + *out = *in; + return TRUE; +} + +METHOD(kernel_net_t, create_address_enumerator, enumerator_t*, + private_kernel_netlink_net_t *this, kernel_address_type_t which) +{ + address_enumerator_t *data; + + INIT(data, + .this = this, + .which = which, + ); + + this->lock->read_lock(this->lock); + return enumerator_create_nested( + enumerator_create_filter( + this->ifaces->create_enumerator(this->ifaces), + (void*)filter_interfaces, data, NULL), + (void*)create_iface_enumerator, data, + (void*)address_enumerator_destroy); +} + +METHOD(kernel_net_t, get_interface_name, bool, + private_kernel_netlink_net_t *this, host_t* ip, char **name) +{ + addr_map_entry_t *entry, lookup = { + .ip = ip, + }; + + if (ip->is_anyaddr(ip)) + { + return FALSE; + } + this->lock->read_lock(this->lock); + /* first try to find it on an up and usable interface */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_up_and_usable); + if (entry) + { + if (name) + { + *name = strdup(entry->iface->ifname); + DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + } + this->lock->unlock(this->lock); + return TRUE; + } + /* in a second step, consider virtual IPs installed by us */ + entry = this->vips->get_match(this->vips, &lookup, + (void*)addr_map_entry_match_up_and_usable); + if (entry) + { + if (name) + { + *name = strdup(entry->iface->ifname); + DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name); + } + this->lock->unlock(this->lock); + return TRUE; + } + /* maybe it is installed on an ignored interface */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_up); + if (!entry) + { + DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip); + } + this->lock->unlock(this->lock); + return FALSE; +} + +/** + * get the index of an interface by name + */ +static int get_interface_index(private_kernel_netlink_net_t *this, char* name) +{ + iface_entry_t *iface; + int ifindex = 0; + + DBG2(DBG_KNL, "getting iface index for %s", name); + + this->lock->read_lock(this->lock); + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name, + (void**)&iface, name) == SUCCESS) + { + ifindex = iface->ifindex; + } + this->lock->unlock(this->lock); + + if (ifindex == 0) + { + DBG1(DBG_KNL, "unable to get interface index for %s", name); + } + return ifindex; +} + +/** + * check if an address or net (addr with prefix net bits) is in + * subnet (net with net_len net bits) + */ +static bool addr_in_subnet(chunk_t addr, int prefix, chunk_t net, int net_len) +{ + static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; + int byte = 0; + + if (net_len == 0) + { /* any address matches a /0 network */ + return TRUE; + } + if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len) + { + return FALSE; + } + /* scan through all bytes in network order */ + while (net_len > 0) + { + if (net_len < 8) + { + return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]); + } + else + { + if (addr.ptr[byte] != net.ptr[byte]) + { + return FALSE; + } + byte++; + net_len -= 8; + } + } + return TRUE; +} + +/** + * Store information about a route retrieved via RTNETLINK + */ +typedef struct { + chunk_t gtw; + chunk_t src; + chunk_t dst; + host_t *src_host; + u_int8_t dst_len; + u_int32_t table; + u_int32_t oif; + u_int32_t priority; +} rt_entry_t; + +/** + * Free a route entry + */ +static void rt_entry_destroy(rt_entry_t *this) +{ + DESTROY_IF(this->src_host); + free(this); +} + +/** + * Check if the route received with RTM_NEWROUTE is usable based on its type. + */ +static bool route_usable(struct nlmsghdr *hdr) +{ + struct rtmsg *msg; + + msg = NLMSG_DATA(hdr); + switch (msg->rtm_type) + { + case RTN_BLACKHOLE: + case RTN_UNREACHABLE: + case RTN_PROHIBIT: + case RTN_THROW: + return FALSE; + default: + return TRUE; + } +} + +/** + * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be + * reused if not NULL. + * + * Returned chunks point to internal data of the Netlink message. + */ +static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route) +{ + struct rtattr *rta; + struct rtmsg *msg; + size_t rtasize; + + msg = NLMSG_DATA(hdr); + rta = RTM_RTA(msg); + rtasize = RTM_PAYLOAD(hdr); + + if (route) + { + route->gtw = chunk_empty; + route->src = chunk_empty; + route->dst = chunk_empty; + route->dst_len = msg->rtm_dst_len; + route->table = msg->rtm_table; + route->oif = 0; + route->priority = 0; + } + else + { + INIT(route, + .dst_len = msg->rtm_dst_len, + .table = msg->rtm_table, + ); + } + + while (RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case RTA_PREFSRC: + route->src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + case RTA_GATEWAY: + route->gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + case RTA_DST: + route->dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + case RTA_OIF: + if (RTA_PAYLOAD(rta) == sizeof(route->oif)) + { + route->oif = *(u_int32_t*)RTA_DATA(rta); + } + break; + case RTA_PRIORITY: + if (RTA_PAYLOAD(rta) == sizeof(route->priority)) + { + route->priority = *(u_int32_t*)RTA_DATA(rta); + } + break; +#ifdef HAVE_RTA_TABLE + case RTA_TABLE: + if (RTA_PAYLOAD(rta) == sizeof(route->table)) + { + route->table = *(u_int32_t*)RTA_DATA(rta); + } + break; +#endif /* HAVE_RTA_TABLE*/ + } + rta = RTA_NEXT(rta, rtasize); + } + return route; +} + +/** + * Get a route: If "nexthop", the nexthop is returned. source addr otherwise. + */ +static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, + int prefix, bool nexthop, host_t *candidate, + u_int recursion) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out, *current; + struct rtmsg *msg; + chunk_t chunk; + size_t len; + linked_list_t *routes; + rt_entry_t *route = NULL, *best = NULL; + enumerator_t *enumerator; + host_t *addr = NULL; + bool match_net; + int family; + + if (recursion > MAX_ROUTE_RECURSION) + { + return NULL; + } + chunk = dest->get_address(dest); + len = chunk.len * 8; + prefix = prefix < 0 ? len : min(prefix, len); + match_net = prefix != len; + + memset(&request, 0, sizeof(request)); + + family = dest->get_family(dest); + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = RTM_GETROUTE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + + msg = NLMSG_DATA(hdr); + msg->rtm_family = family; + if (!match_net && this->rta_mark && this->routing_mark.value) + { + /* if our routing rule excludes packets with a certain mark we can + * get the preferred route without having to dump all routes */ + chunk = chunk_from_thing(this->routing_mark.value); + netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request)); + } + else if (family == AF_INET || this->rta_prefsrc_for_ipv6 || + this->routing_table || match_net) + { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes. + * as we want to ignore routes with virtual IPs we cannot use DUMP + * if these routes are not installed in a separate table */ + hdr->nlmsg_flags |= NLM_F_DUMP; + } + if (candidate) + { + chunk = candidate->get_address(candidate); + netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request)); + } + /* we use this below to match against the routes */ + chunk = dest->get_address(dest); + if (!match_net) + { + netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request)); + } + + if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS) + { + DBG2(DBG_KNL, "getting %s to reach %H/%d failed", + nexthop ? "nexthop" : "address", dest, prefix); + return NULL; + } + routes = linked_list_create(); + this->lock->read_lock(this->lock); + + for (current = out; NLMSG_OK(current, len); + current = NLMSG_NEXT(current, len)) + { + switch (current->nlmsg_type) + { + case NLMSG_DONE: + break; + case RTM_NEWROUTE: + { + rt_entry_t *other; + uintptr_t table; + + if (!route_usable(current)) + { + continue; + } + route = parse_route(current, route); + + table = (uintptr_t)route->table; + if (this->rt_exclude->find_first(this->rt_exclude, NULL, + (void**)&table) == SUCCESS) + { /* route is from an excluded routing table */ + continue; + } + if (this->routing_table != 0 && + route->table == this->routing_table) + { /* route is from our own ipsec routing table */ + continue; + } + if (route->oif && !is_interface_up_and_usable(this, route->oif)) + { /* interface is down */ + continue; + } + if (!addr_in_subnet(chunk, prefix, route->dst, route->dst_len)) + { /* route destination does not contain dest */ + continue; + } + if (route->src.ptr) + { /* verify source address, if any */ + host_t *src = host_create_from_chunk(msg->rtm_family, + route->src, 0); + if (src && is_known_vip(this, src)) + { /* ignore routes installed by us */ + src->destroy(src); + continue; + } + route->src_host = src; + } + /* insert route, sorted by priority and network prefix */ + enumerator = routes->create_enumerator(routes); + while (enumerator->enumerate(enumerator, &other)) + { + if (route->priority < other->priority) + { + break; + } + if (route->priority == other->priority && + route->dst_len > other->dst_len) + { + break; + } + } + routes->insert_before(routes, enumerator, route); + enumerator->destroy(enumerator); + route = NULL; + continue; + } + default: + continue; + } + break; + } + if (route) + { + rt_entry_destroy(route); + } + + /* now we have a list of routes matching dest, sorted by net prefix. + * we will look for source addresses for these routes and select the one + * with the preferred source address, if possible */ + enumerator = routes->create_enumerator(routes); + while (enumerator->enumerate(enumerator, &route)) + { + if (route->src_host) + { /* got a source address with the route, if no preferred source + * is given or it matches we are done, as this is the best route */ + if (!candidate || candidate->ip_equals(candidate, route->src_host)) + { + best = route; + break; + } + else if (route->oif) + { /* no match yet, maybe it is assigned to the same interface */ + host_t *src = get_interface_address(this, route->oif, + msg->rtm_family, dest, candidate); + if (src && src->ip_equals(src, candidate)) + { + route->src_host->destroy(route->src_host); + route->src_host = src; + best = route; + break; + } + DESTROY_IF(src); + } + /* no luck yet with the source address. if this is the best (first) + * route we store it as fallback in case we don't find a route with + * the preferred source */ + best = best ?: route; + continue; + } + if (route->oif) + { /* no src, but an interface - get address from it */ + route->src_host = get_interface_address(this, route->oif, + msg->rtm_family, dest, candidate); + if (route->src_host) + { /* we handle this address the same as the one above */ + if (!candidate || + candidate->ip_equals(candidate, route->src_host)) + { + best = route; + break; + } + best = best ?: route; + continue; + } + } + if (route->gtw.ptr) + { /* no src, no iface, but a gateway - lookup src to reach gtw */ + host_t *gtw; + + gtw = host_create_from_chunk(msg->rtm_family, route->gtw, 0); + if (gtw && !gtw->ip_equals(gtw, dest)) + { + route->src_host = get_route(this, gtw, -1, FALSE, candidate, + recursion + 1); + } + DESTROY_IF(gtw); + if (route->src_host) + { /* more of the same */ + if (!candidate || + candidate->ip_equals(candidate, route->src_host)) + { + best = route; + break; + } + best = best ?: route; + } + } + } + enumerator->destroy(enumerator); + + if (nexthop) + { /* nexthop lookup, return gateway if any */ + if (best || routes->get_first(routes, (void**)&best) == SUCCESS) + { + addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0); + } + if (!addr && !match_net) + { /* fallback to destination address */ + addr = dest->clone(dest); + } + } + else + { + if (best) + { + addr = best->src_host->clone(best->src_host); + } + } + this->lock->unlock(this->lock); + routes->destroy_function(routes, (void*)rt_entry_destroy); + free(out); + + if (addr) + { + DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr, + nexthop ? "nexthop" : "address", dest, prefix); + } + else if (!recursion) + { + DBG2(DBG_KNL, "no %s found to reach %H/%d", + nexthop ? "nexthop" : "address", dest, prefix); + } + return addr; +} + +METHOD(kernel_net_t, get_source_addr, host_t*, + private_kernel_netlink_net_t *this, host_t *dest, host_t *src) +{ + return get_route(this, dest, -1, FALSE, src, 0); +} + +METHOD(kernel_net_t, get_nexthop, host_t*, + private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src) +{ + return get_route(this, dest, prefix, TRUE, src, 0); +} + +/** + * Manages the creation and deletion of ip addresses on an interface. + * By setting the appropriate nlmsg_type, the ip will be set or unset. + */ +static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type, + int flags, int if_index, host_t *ip, int prefix) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct ifaddrmsg *msg; + chunk_t chunk; + + memset(&request, 0, sizeof(request)); + + chunk = ip->get_address(ip); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; + hdr->nlmsg_type = nlmsg_type; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + + msg = NLMSG_DATA(hdr); + msg->ifa_family = ip->get_family(ip); + msg->ifa_flags = 0; + msg->ifa_prefixlen = prefix < 0 ? chunk.len * 8 : prefix; + msg->ifa_scope = RT_SCOPE_UNIVERSE; + msg->ifa_index = if_index; + + netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request)); + + if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6) + { /* if source routes are possible we let the virtual IP get deprecated + * immediately (but mark it as valid forever) so it gets only used if + * forced by our route, and not by the default IPv6 address selection */ + struct ifa_cacheinfo cache = { + .ifa_valid = 0xFFFFFFFF, + .ifa_prefered = 0, + }; + netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache), + sizeof(request)); + } + return this->socket->send_ack(this->socket, hdr); +} + +METHOD(kernel_net_t, add_ip, status_t, + private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix, + char *iface_name) +{ + addr_map_entry_t *entry, lookup = { + .ip = virtual_ip, + }; + iface_entry_t *iface = NULL; + + if (!this->install_virtual_ip) + { /* disabled by config */ + return SUCCESS; + } + + this->lock->write_lock(this->lock); + /* the virtual IP might actually be installed as regular IP, in which case + * we don't track it as virtual IP */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match); + if (!entry) + { /* otherwise it might already be installed as virtual IP */ + entry = this->vips->get_match(this->vips, &lookup, + (void*)addr_map_entry_match); + if (entry) + { /* the vip we found can be in one of three states: 1) installed and + * ready, 2) just added by another thread, but not yet confirmed to + * be installed by the kernel, 3) just deleted, but not yet gone. + * Then while we wait below, several things could happen (as we + * release the lock). For instance, the interface could disappear, + * or the IP is finally deleted, and it reappears on a different + * interface. All these cases are handled by the call below. */ + while (!is_vip_installed_or_gone(this, virtual_ip, &entry)) + { + this->condvar->wait(this->condvar, this->lock); + } + if (entry) + { + entry->addr->refcount++; + } + } + } + if (entry) + { + DBG2(DBG_KNL, "virtual IP %H is already installed on %s", virtual_ip, + entry->iface->ifname); + this->lock->unlock(this->lock); + return SUCCESS; + } + /* try to find the target interface, either by config or via src ip */ + if (!this->install_virtual_ip_on || + this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name, + (void**)&iface, this->install_virtual_ip_on) != SUCCESS) + { + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name, + (void**)&iface, iface_name) != SUCCESS) + { /* if we don't find the requested interface we just use the first */ + this->ifaces->get_first(this->ifaces, (void**)&iface); + } + } + if (iface) + { + addr_entry_t *addr; + char *ifname; + int ifi; + + INIT(addr, + .ip = virtual_ip->clone(virtual_ip), + .refcount = 1, + .scope = RT_SCOPE_UNIVERSE, + ); + iface->addrs->insert_last(iface->addrs, addr); + addr_map_entry_add(this->vips, addr, iface); + ifi = iface->ifindex; + this->lock->unlock(this->lock); + if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL, + ifi, virtual_ip, prefix) == SUCCESS) + { + this->lock->write_lock(this->lock); + while (!is_vip_installed_or_gone(this, virtual_ip, &entry)) + { /* wait until address appears */ + this->condvar->wait(this->condvar, this->lock); + } + if (entry) + { /* we fail if the interface got deleted in the meantime */ + ifname = strdup(entry->iface->ifname); + this->lock->unlock(this->lock); + DBG2(DBG_KNL, "virtual IP %H installed on %s", + virtual_ip, ifname); + /* during IKEv1 reauthentication, children get moved from + * old the new SA before the virtual IP is available. This + * kills the route for our virtual IP, reinstall. */ + queue_route_reinstall(this, ifname); + return SUCCESS; + } + this->lock->unlock(this->lock); + } + DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip); + return FAILED; + } + this->lock->unlock(this->lock); + DBG1(DBG_KNL, "no interface available, unable to install virtual IP %H", + virtual_ip); + return FAILED; +} + +METHOD(kernel_net_t, del_ip, status_t, + private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix, + bool wait) +{ + addr_map_entry_t *entry, lookup = { + .ip = virtual_ip, + }; + + if (!this->install_virtual_ip) + { /* disabled by config */ + return SUCCESS; + } + + DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip); + + this->lock->write_lock(this->lock); + entry = this->vips->get_match(this->vips, &lookup, + (void*)addr_map_entry_match); + if (!entry) + { /* we didn't install this IP as virtual IP */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match); + if (entry) + { + DBG2(DBG_KNL, "not deleting existing IP %H on %s", virtual_ip, + entry->iface->ifname); + this->lock->unlock(this->lock); + return SUCCESS; + } + DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip); + this->lock->unlock(this->lock); + return FAILED; + } + if (entry->addr->refcount == 1) + { + status_t status; + int ifi; + + /* we set this flag so that threads calling add_ip will block and wait + * until the entry is gone, also so we can wait below */ + entry->addr->installed = FALSE; + ifi = entry->iface->ifindex; + this->lock->unlock(this->lock); + status = manage_ipaddr(this, RTM_DELADDR, 0, ifi, virtual_ip, prefix); + if (status == SUCCESS && wait) + { /* wait until the address is really gone */ + this->lock->write_lock(this->lock); + while (is_known_vip(this, virtual_ip)) + { + this->condvar->wait(this->condvar, this->lock); + } + this->lock->unlock(this->lock); + } + return status; + } + else + { + entry->addr->refcount--; + } + DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting", + virtual_ip); + this->lock->unlock(this->lock); + return SUCCESS; +} + +/** + * Manages source routes in the routing table. + * By setting the appropriate nlmsg_type, the route gets added or removed. + */ +static status_t manage_srcroute(private_kernel_netlink_net_t *this, + int nlmsg_type, int flags, chunk_t dst_net, + u_int8_t prefixlen, host_t *gateway, + host_t *src_ip, char *if_name) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct rtmsg *msg; + struct rtattr *rta; + int ifindex; + chunk_t chunk; + + /* if route is 0.0.0.0/0, we can't install it, as it would + * overwrite the default route. Instead, we add two routes: + * 0.0.0.0/1 and 128.0.0.0/1 */ + if (this->routing_table == 0 && prefixlen == 0) + { + chunk_t half_net; + u_int8_t half_prefixlen; + status_t status; + + half_net = chunk_alloca(dst_net.len); + memset(half_net.ptr, 0, half_net.len); + half_prefixlen = 1; + + status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen, + gateway, src_ip, if_name); + half_net.ptr[0] |= 0x80; + status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen, + gateway, src_ip, if_name); + return status; + } + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; + hdr->nlmsg_type = nlmsg_type; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + + msg = NLMSG_DATA(hdr); + msg->rtm_family = src_ip->get_family(src_ip); + msg->rtm_dst_len = prefixlen; + msg->rtm_table = this->routing_table; + msg->rtm_protocol = RTPROT_STATIC; + msg->rtm_type = RTN_UNICAST; + msg->rtm_scope = RT_SCOPE_UNIVERSE; + + netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request)); + chunk = src_ip->get_address(src_ip); + netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request)); + if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip)) + { + chunk = gateway->get_address(gateway); + netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request)); + } + ifindex = get_interface_index(this, if_name); + chunk.ptr = (char*)&ifindex; + chunk.len = sizeof(ifindex); + netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request)); + + if (this->mtu || this->mss) + { + chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) + + sizeof(u_int32_t)) * 2)); + chunk.len = 0; + rta = (struct rtattr*)chunk.ptr; + if (this->mtu) + { + rta->rta_type = RTAX_MTU; + rta->rta_len = RTA_LENGTH(sizeof(u_int32_t)); + memcpy(RTA_DATA(rta), &this->mtu, sizeof(u_int32_t)); + chunk.len = rta->rta_len; + } + if (this->mss) + { + rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len)); + rta->rta_type = RTAX_ADVMSS; + rta->rta_len = RTA_LENGTH(sizeof(u_int32_t)); + memcpy(RTA_DATA(rta), &this->mss, sizeof(u_int32_t)); + chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len; + } + netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request)); + } + + return this->socket->send_ack(this->socket, hdr); +} + +METHOD(kernel_net_t, add_route, status_t, + private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) +{ + status_t status; + route_entry_t *found, route = { + .dst_net = dst_net, + .prefixlen = prefixlen, + .gateway = gateway, + .src_ip = src_ip, + .if_name = if_name, + }; + + this->routes_lock->lock(this->routes_lock); + found = this->routes->get(this->routes, &route); + if (found) + { + this->routes_lock->unlock(this->routes_lock); + return ALREADY_DONE; + } + status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, + dst_net, prefixlen, gateway, src_ip, if_name); + if (status == SUCCESS) + { + found = route_entry_clone(&route); + this->routes->put(this->routes, found, found); + } + this->routes_lock->unlock(this->routes_lock); + return status; +} + +METHOD(kernel_net_t, del_route, status_t, + private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) +{ + status_t status; + route_entry_t *found, route = { + .dst_net = dst_net, + .prefixlen = prefixlen, + .gateway = gateway, + .src_ip = src_ip, + .if_name = if_name, + }; + + this->routes_lock->lock(this->routes_lock); + found = this->routes->get(this->routes, &route); + if (!found) + { + this->routes_lock->unlock(this->routes_lock); + return NOT_FOUND; + } + this->routes->remove(this->routes, found); + route_entry_destroy(found); + status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen, + gateway, src_ip, if_name); + this->routes_lock->unlock(this->routes_lock); + return status; +} + +/** + * Initialize a list of local addresses. + */ +static status_t init_address_list(private_kernel_netlink_net_t *this) +{ + netlink_buf_t request; + struct nlmsghdr *out, *current, *in; + struct rtgenmsg *msg; + size_t len; + enumerator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; + + DBG2(DBG_KNL, "known interfaces and IP addresses:"); + + memset(&request, 0, sizeof(request)); + + in = &request.hdr; + in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); + in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT; + msg = NLMSG_DATA(in); + msg->rtgen_family = AF_UNSPEC; + + /* get all links */ + in->nlmsg_type = RTM_GETLINK; + if (this->socket->send(this->socket, in, &out, &len) != SUCCESS) + { + return FAILED; + } + current = out; + while (NLMSG_OK(current, len)) + { + switch (current->nlmsg_type) + { + case NLMSG_DONE: + break; + case RTM_NEWLINK: + process_link(this, current, FALSE); + /* fall through */ + default: + current = NLMSG_NEXT(current, len); + continue; + } + break; + } + free(out); + + /* get all interface addresses */ + in->nlmsg_type = RTM_GETADDR; + if (this->socket->send(this->socket, in, &out, &len) != SUCCESS) + { + return FAILED; + } + current = out; + while (NLMSG_OK(current, len)) + { + switch (current->nlmsg_type) + { + case NLMSG_DONE: + break; + case RTM_NEWADDR: + process_addr(this, current, FALSE); + /* fall through */ + default: + current = NLMSG_NEXT(current, len); + continue; + } + break; + } + free(out); + + this->lock->read_lock(this->lock); + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (iface_entry_up_and_usable(iface)) + { + DBG2(DBG_KNL, " %s", iface->ifname); + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, (void**)&addr)) + { + DBG2(DBG_KNL, " %H", addr->ip); + } + addrs->destroy(addrs); + } + } + ifaces->destroy(ifaces); + this->lock->unlock(this->lock); + return SUCCESS; +} + +/** + * create or delete a rule to use our routing table + */ +static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type, + int family, u_int32_t table, u_int32_t prio) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct rtmsg *msg; + chunk_t chunk; + char *fwmark; + + memset(&request, 0, sizeof(request)); + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_type = nlmsg_type; + if (nlmsg_type == RTM_NEWRULE) + { + hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + } + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + + msg = NLMSG_DATA(hdr); + msg->rtm_table = table; + msg->rtm_family = family; + msg->rtm_protocol = RTPROT_BOOT; + msg->rtm_scope = RT_SCOPE_UNIVERSE; + msg->rtm_type = RTN_UNICAST; + + chunk = chunk_from_thing(prio); + netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request)); + + fwmark = lib->settings->get_str(lib->settings, + "%s.plugins.kernel-netlink.fwmark", NULL, lib->ns); + if (fwmark) + { +#ifdef HAVE_LINUX_FIB_RULES_H + mark_t mark; + + if (fwmark[0] == '!') + { + msg->rtm_flags |= FIB_RULE_INVERT; + fwmark++; + } + if (mark_from_string(fwmark, &mark)) + { + chunk = chunk_from_thing(mark.value); + netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request)); + chunk = chunk_from_thing(mark.mask); + netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request)); + if (msg->rtm_flags & FIB_RULE_INVERT) + { + this->routing_mark = mark; + } + } +#else + DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported"); +#endif + } + return this->socket->send_ack(this->socket, hdr); +} + +/** + * check for kernel features (currently only via version number) + */ +static void check_kernel_features(private_kernel_netlink_net_t *this) +{ + struct utsname utsname; + int a, b, c; + + if (uname(&utsname) == 0) + { + switch(sscanf(utsname.release, "%d.%d.%d", &a, &b, &c)) + { + case 3: + if (a == 2) + { + if (b == 6 && c >= 36) + { + this->rta_mark = TRUE; + } + DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for " + "RTA_PREFSRC for IPv6 routes", a, b, c); + break; + } + /* fall-through */ + case 2: + /* only 3.x+ uses two part version numbers */ + this->rta_prefsrc_for_ipv6 = TRUE; + this->rta_mark = TRUE; + break; + default: + break; + } + } +} + +/** + * Destroy an address to iface map + */ +static void addr_map_destroy(hashtable_t *map) +{ + enumerator_t *enumerator; + addr_map_entry_t *addr; + + enumerator = map->create_enumerator(map); + while (enumerator->enumerate(enumerator, NULL, (void**)&addr)) + { + free(addr); + } + enumerator->destroy(enumerator); + map->destroy(map); +} + +METHOD(kernel_net_t, destroy, void, + private_kernel_netlink_net_t *this) +{ + enumerator_t *enumerator; + route_entry_t *route; + + if (this->routing_table) + { + manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table, + this->routing_table_prio); + manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table, + this->routing_table_prio); + } + if (this->socket_events > 0) + { + lib->watcher->remove(lib->watcher, this->socket_events); + close(this->socket_events); + } + enumerator = this->routes->create_enumerator(this->routes); + while (enumerator->enumerate(enumerator, NULL, (void**)&route)) + { + manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen, + route->gateway, route->src_ip, route->if_name); + route_entry_destroy(route); + } + enumerator->destroy(enumerator); + this->routes->destroy(this->routes); + this->routes_lock->destroy(this->routes_lock); + DESTROY_IF(this->socket); + + net_changes_clear(this); + this->net_changes->destroy(this->net_changes); + this->net_changes_lock->destroy(this->net_changes_lock); + + addr_map_destroy(this->addrs); + addr_map_destroy(this->vips); + + this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy); + this->rt_exclude->destroy(this->rt_exclude); + this->roam_lock->destroy(this->roam_lock); + this->condvar->destroy(this->condvar); + this->lock->destroy(this->lock); + free(this); +} + +/* + * Described in header. + */ +kernel_netlink_net_t *kernel_netlink_net_create() +{ + private_kernel_netlink_net_t *this; + enumerator_t *enumerator; + bool register_for_events = TRUE; + char *exclude; + + INIT(this, + .public = { + .interface = { + .get_interface = _get_interface_name, + .create_address_enumerator = _create_address_enumerator, + .get_source_addr = _get_source_addr, + .get_nexthop = _get_nexthop, + .add_ip = _add_ip, + .del_ip = _del_ip, + .add_route = _add_route, + .del_route = _del_route, + .destroy = _destroy, + }, + }, + .socket = netlink_socket_create(NETLINK_ROUTE, rt_msg_names, + lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.parallel_route", FALSE, lib->ns)), + .rt_exclude = linked_list_create(), + .routes = hashtable_create((hashtable_hash_t)route_entry_hash, + (hashtable_equals_t)route_entry_equals, 16), + .net_changes = hashtable_create( + (hashtable_hash_t)net_change_hash, + (hashtable_equals_t)net_change_equals, 16), + .addrs = hashtable_create( + (hashtable_hash_t)addr_map_entry_hash, + (hashtable_equals_t)addr_map_entry_equals, 16), + .vips = hashtable_create((hashtable_hash_t)addr_map_entry_hash, + (hashtable_equals_t)addr_map_entry_equals, 16), + .routes_lock = mutex_create(MUTEX_TYPE_DEFAULT), + .net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT), + .ifaces = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .condvar = rwlock_condvar_create(), + .roam_lock = spinlock_create(), + .routing_table = lib->settings->get_int(lib->settings, + "%s.routing_table", ROUTING_TABLE, lib->ns), + .routing_table_prio = lib->settings->get_int(lib->settings, + "%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns), + .process_route = lib->settings->get_bool(lib->settings, + "%s.process_route", TRUE, lib->ns), + .install_virtual_ip = lib->settings->get_bool(lib->settings, + "%s.install_virtual_ip", TRUE, lib->ns), + .install_virtual_ip_on = lib->settings->get_str(lib->settings, + "%s.install_virtual_ip_on", NULL, lib->ns), + .prefer_temporary_addrs = lib->settings->get_bool(lib->settings, + "%s.prefer_temporary_addrs", FALSE, lib->ns), + .roam_events = lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.roam_events", TRUE, lib->ns), + .mtu = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.mtu", 0, lib->ns), + .mss = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.mss", 0, lib->ns), + ); + timerclear(&this->last_route_reinstall); + timerclear(&this->next_roam); + + check_kernel_features(this); + + if (streq(lib->ns, "starter")) + { /* starter has no threads, so we do not register for kernel events */ + register_for_events = FALSE; + } + + exclude = lib->settings->get_str(lib->settings, + "%s.ignore_routing_tables", NULL, lib->ns); + if (exclude) + { + char *token; + uintptr_t table; + + enumerator = enumerator_create_token(exclude, " ", " "); + while (enumerator->enumerate(enumerator, &token)) + { + errno = 0; + table = strtoul(token, NULL, 10); + + if (errno == 0) + { + this->rt_exclude->insert_last(this->rt_exclude, (void*)table); + } + } + enumerator->destroy(enumerator); + } + + if (register_for_events) + { + struct sockaddr_nl addr; + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + + /* create and bind RT socket for events (address/interface/route changes) */ + this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (this->socket_events < 0) + { + DBG1(DBG_KNL, "unable to create RT event socket"); + destroy(this); + return NULL; + } + addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | + RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK; + if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr))) + { + DBG1(DBG_KNL, "unable to bind RT event socket"); + destroy(this); + return NULL; + } + + lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ, + (watcher_cb_t)receive_events, this); + } + + if (init_address_list(this) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get interface list"); + destroy(this); + return NULL; + } + + if (this->routing_table) + { + if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table, + this->routing_table_prio) != SUCCESS) + { + DBG1(DBG_KNL, "unable to create IPv4 routing table rule"); + } + if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table, + this->routing_table_prio) != SUCCESS) + { + DBG1(DBG_KNL, "unable to create IPv6 routing table rule"); + } + } + + return &this->public; +} diff --git a/src/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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..8bafc3c55 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "kernel_netlink_plugin.h" + +#include "kernel_netlink_ipsec.h" +#include "kernel_netlink_net.h" + +typedef struct private_kernel_netlink_plugin_t private_kernel_netlink_plugin_t; + +/** + * private data of kernel netlink plugin + */ +struct private_kernel_netlink_plugin_t { + /** + * implements plugin interface + */ + kernel_netlink_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_kernel_netlink_plugin_t *this) +{ + return "kernel-netlink"; +} + +METHOD(plugin_t, get_features, int, + private_kernel_netlink_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_kernel_netlink_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *kernel_netlink_plugin_create() +{ + private_kernel_netlink_plugin_t *this; + + if (!lib->caps->keep(lib->caps, CAP_NET_ADMIN)) + { /* required to bind/use XFRM sockets / create/modify routing tables, but + * not if only the read-only parts of kernel-netlink-net are used, so + * we don't fail here */ + DBG1(DBG_KNL, "kernel-netlink plugin might require CAP_NET_ADMIN " + "capability"); + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h new file mode 100644 index 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..f7ce992a3 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c @@ -0,0 +1,655 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 revosec AG + * 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include "kernel_netlink_shared.h" + +#include +#include +#include +#include +#include + +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 entries + */ + mutex_t *mutex; + + /** + * Netlink request entries currently active, uintptr_t seq => entry_t + */ + hashtable_t *entries; + + /** + * Current sequence number for Netlink requests + */ + refcount_t seq; + + /** + * netlink socket + */ + int socket; + + /** + * Netlink protocol + */ + int protocol; + + /** + * Enum names for Netlink messages + */ + enum_name_t *names; + + /** + * Timeout for Netlink replies, in ms + */ + u_int timeout; + + /** + * Number of times to repeat timed out queries + */ + u_int retries; + + /** + * Buffer size for received Netlink messages + */ + u_int buflen; + + /** + * Use parallel netlink queries + */ + bool parallel; + + /** + * Ignore errors potentially resulting from a retransmission + */ + bool ignore_retransmit_errors; +}; + +/** + * #definable hook to simulate request message loss + */ +#ifdef NETLINK_MSG_LOSS_HOOK +bool NETLINK_MSG_LOSS_HOOK(struct nlmsghdr *msg); +#define msg_loss_hook(msg) NETLINK_MSG_LOSS_HOOK(msg) +#else +#define msg_loss_hook(msg) FALSE +#endif + +/** + * Request entry the answer for a waiting thread is collected in + */ +typedef struct { + /** Condition variable thread is waiting */ + condvar_t *condvar; + /** Array of hdrs in a multi-message response, as struct nlmsghdr* */ + array_t *hdrs; + /** All response messages received? */ + bool complete; +} entry_t; + +/** + * Clean up a thread waiting entry + */ +static void destroy_entry(entry_t *entry) +{ + entry->condvar->destroy(entry->condvar); + array_destroy_function(entry->hdrs, (void*)free, NULL); + free(entry); +} + +/** + * Write a Netlink message to socket + */ +static bool write_msg(private_netlink_socket_t *this, struct nlmsghdr *msg) +{ + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + }; + int len; + + if (msg_loss_hook(msg)) + { + return TRUE; + } + + while (TRUE) + { + len = sendto(this->socket, msg, msg->nlmsg_len, 0, + (struct sockaddr*)&addr, sizeof(addr)); + if (len != msg->nlmsg_len) + { + if (errno == EINTR) + { + continue; + } + DBG1(DBG_KNL, "netlink write error: %s", strerror(errno)); + return FALSE; + } + return TRUE; + } +} + +/** + * Read a single Netlink message from socket, return 0 on error, -1 on timeout + */ +static ssize_t read_msg(private_netlink_socket_t *this, + char *buf, size_t buflen, bool block) +{ + ssize_t len; + + if (block) + { + fd_set set; + timeval_t tv = {}; + + FD_ZERO(&set); + FD_SET(this->socket, &set); + timeval_add_ms(&tv, this->timeout); + + if (select(this->socket + 1, &set, NULL, NULL, + this->timeout ? &tv : NULL) <= 0) + { + return -1; + } + } + len = recv(this->socket, buf, buflen, MSG_TRUNC|(block ? 0 : MSG_DONTWAIT)); + if (len > buflen) + { + DBG1(DBG_KNL, "netlink response exceeds buffer size"); + return 0; + } + if (len < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + DBG1(DBG_KNL, "netlink read error: %s", strerror(errno)); + } + return 0; + } + return len; +} + +/** + * Queue received response message + */ +static bool queue(private_netlink_socket_t *this, struct nlmsghdr *buf) +{ + struct nlmsghdr *hdr; + entry_t *entry; + uintptr_t seq; + + seq = (uintptr_t)buf->nlmsg_seq; + + this->mutex->lock(this->mutex); + entry = this->entries->get(this->entries, (void*)seq); + if (entry) + { + hdr = malloc(buf->nlmsg_len); + memcpy(hdr, buf, buf->nlmsg_len); + array_insert(entry->hdrs, ARRAY_TAIL, hdr); + if (hdr->nlmsg_type == NLMSG_DONE || !(hdr->nlmsg_flags & NLM_F_MULTI)) + { + entry->complete = TRUE; + entry->condvar->signal(entry->condvar); + } + } + else + { + DBG1(DBG_KNL, "received unknown netlink seq %u, ignored", seq); + } + this->mutex->unlock(this->mutex); + + return entry != NULL; +} + +/** + * Read and queue response message, optionally blocking, returns TRUE on timeout + */ +static bool read_and_queue(private_netlink_socket_t *this, bool block) +{ + struct nlmsghdr *hdr; + char buf[this->buflen]; + ssize_t len; + + len = read_msg(this, buf, sizeof(buf), block); + if (len == -1) + { + return TRUE; + } + if (len) + { + hdr = (struct nlmsghdr*)buf; + while (NLMSG_OK(hdr, len)) + { + if (!queue(this, hdr)) + { + break; + } + hdr = NLMSG_NEXT(hdr, len); + } + } + return FALSE; +} + +CALLBACK(watch, bool, + private_netlink_socket_t *this, int fd, watcher_event_t event) +{ + if (event == WATCHER_READ) + { + read_and_queue(this, FALSE); + } + return TRUE; +} + +/** + * Send a netlink request, try once + */ +static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, + uintptr_t seq, struct nlmsghdr **out, size_t *out_len) +{ + struct nlmsghdr *hdr; + chunk_t result = {}; + entry_t *entry; + + in->nlmsg_seq = seq; + in->nlmsg_pid = getpid(); + + if (this->names) + { + DBG3(DBG_KNL, "sending %N %u: %b", this->names, in->nlmsg_type, + (u_int)seq, in, in->nlmsg_len); + } + + this->mutex->lock(this->mutex); + if (!write_msg(this, in)) + { + this->mutex->unlock(this->mutex); + return FAILED; + } + + INIT(entry, + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .hdrs = array_create(0, 0), + ); + this->entries->put(this->entries, (void*)seq, entry); + + while (!entry->complete) + { + if (this->parallel && + lib->watcher->get_state(lib->watcher) == WATCHER_RUNNING) + { + if (this->timeout) + { + if (entry->condvar->timed_wait(entry->condvar, this->mutex, + this->timeout)) + { + break; + } + } + else + { + entry->condvar->wait(entry->condvar, this->mutex); + } + } + else + { /* During (de-)initialization, no watcher thread is active. + * collect responses ourselves. */ + if (read_and_queue(this, TRUE)) + { + break; + } + } + } + this->entries->remove(this->entries, (void*)seq); + + this->mutex->unlock(this->mutex); + + if (!entry->complete) + { /* timeout */ + destroy_entry(entry); + return OUT_OF_RES; + } + + while (array_remove(entry->hdrs, ARRAY_HEAD, &hdr)) + { + if (this->names) + { + DBG3(DBG_KNL, "received %N %u: %b", this->names, hdr->nlmsg_type, + hdr->nlmsg_seq, hdr, hdr->nlmsg_len); + } + result = chunk_cat("mm", result, + chunk_create((char*)hdr, hdr->nlmsg_len)); + } + destroy_entry(entry); + + *out_len = result.len; + *out = (struct nlmsghdr*)result.ptr; + + return SUCCESS; +} + +/** + * Ignore errors for message types that might have completed previously + */ +static void ignore_retransmit_error(private_netlink_socket_t *this, + struct nlmsgerr *err, int type) +{ + switch (err->error) + { + case -EEXIST: + switch (this->protocol) + { + case NETLINK_XFRM: + switch (type) + { + case XFRM_MSG_NEWPOLICY: + case XFRM_MSG_NEWSA: + err->error = 0; + break; + } + break; + case NETLINK_ROUTE: + switch (type) + { + case RTM_NEWADDR: + case RTM_NEWLINK: + case RTM_NEWNEIGH: + case RTM_NEWROUTE: + case RTM_NEWRULE: + err->error = 0; + break; + } + break; + } + break; + case -ENOENT: + switch (this->protocol) + { + case NETLINK_XFRM: + switch (type) + { + case XFRM_MSG_DELPOLICY: + case XFRM_MSG_DELSA: + err->error = 0; + break; + } + break; + case NETLINK_ROUTE: + switch (type) + { + case RTM_DELADDR: + case RTM_DELLINK: + case RTM_DELNEIGH: + case RTM_DELROUTE: + case RTM_DELRULE: + err->error = 0; + break; + } + break; + } + break; + } +} + +METHOD(netlink_socket_t, netlink_send, status_t, + private_netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out, + size_t *out_len) +{ + uintptr_t seq; + u_int try; + + seq = ref_get(&this->seq); + + for (try = 0; try <= this->retries; ++try) + { + struct nlmsghdr *hdr; + status_t status; + size_t len; + + if (try > 0) + { + DBG1(DBG_KNL, "retransmitting Netlink request (%u/%u)", + try, this->retries); + } + status = send_once(this, in, seq, &hdr, &len); + switch (status) + { + case SUCCESS: + break; + case OUT_OF_RES: + continue; + default: + return status; + } + if (hdr->nlmsg_type == NLMSG_ERROR) + { + struct nlmsgerr* err; + + err = NLMSG_DATA(hdr); + if (err->error == -EBUSY) + { + free(hdr); + try--; + continue; + } + if (this->ignore_retransmit_errors && try > 0) + { + ignore_retransmit_error(this, err, in->nlmsg_type); + } + } + *out = hdr; + *out_len = len; + return SUCCESS; + } + DBG1(DBG_KNL, "Netlink request timed out after %u retransmits", + this->retries); + return OUT_OF_RES; +} + +METHOD(netlink_socket_t, netlink_send_ack, status_t, + 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 = NLMSG_DATA(hdr); + + if (err->error) + { + if (-err->error == EEXIST) + { /* do not report existing routes */ + free(out); + return ALREADY_DONE; + } + if (-err->error == ESRCH) + { /* do not report missing entries */ + free(out); + return NOT_FOUND; + } + 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; +} + +METHOD(netlink_socket_t, destroy, void, + private_netlink_socket_t *this) +{ + if (this->socket != -1) + { + if (this->parallel) + { + lib->watcher->remove(lib->watcher, this->socket); + } + close(this->socket); + } + this->entries->destroy(this->entries); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * Described in header. + */ +netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, + bool parallel) +{ + private_netlink_socket_t *this; + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + }; + + INIT(this, + .public = { + .send = _netlink_send, + .send_ack = _netlink_send_ack, + .destroy = _destroy, + }, + .seq = 200, + .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + .socket = socket(AF_NETLINK, SOCK_RAW, protocol), + .entries = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4), + .protocol = protocol, + .names = names, + .buflen = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.buflen", 0, lib->ns), + .timeout = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.timeout", 0, lib->ns), + .retries = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.retries", 0, lib->ns), + .ignore_retransmit_errors = lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.ignore_retransmit_errors", + FALSE, lib->ns), + .parallel = parallel, + ); + + if (!this->buflen) + { + long pagesize = sysconf(_SC_PAGESIZE); + if (pagesize == -1) + { + pagesize = 4096; + } + /* base this on NLMSG_GOODSIZE */ + this->buflen = min(pagesize, 8192); + } + if (this->socket == -1) + { + DBG1(DBG_KNL, "unable to create netlink socket"); + destroy(this); + return NULL; + } + if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr))) + { + DBG1(DBG_KNL, "unable to bind netlink socket"); + destroy(this); + return NULL; + } + if (this->parallel) + { + lib->watcher->add(lib->watcher, this->socket, WATCHER_READ, watch, this); + } + + 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_LENGTH(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; +} + +/** + * Described in header. + */ +void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len) +{ + struct rtattr *rta; + + if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_LENGTH(len) > buflen) + { + DBG1(DBG_KNL, "unable to add attribute, buffer too small"); + return NULL; + } + + rta = ((void*)hdr) + NLMSG_ALIGN(hdr->nlmsg_len); + rta->rta_type = type; + rta->rta_len = RTA_LENGTH(len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len; + + return RTA_DATA(rta); +} 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..b034326d7 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include + +/** + * Default buffer size. + * + * 1024 byte is currently sufficient for all operations. + */ +#ifndef KERNEL_NETLINK_BUFSIZE +#define KERNEL_NETLINK_BUFSIZE 1024 +#endif + +/** + * General purpose netlink buffer. + * + * Some platforms require an enforced aligment to four bytes (e.g. ARM). + */ +typedef union { + struct nlmsghdr hdr; + u_char bytes[KERNEL_NETLINK_BUFSIZE]; +} netlink_buf_t __attribute__((aligned(RTA_ALIGNTO))); + +typedef struct netlink_socket_t netlink_socket_t; + +/** + * Wrapper around a netlink socket. + */ +struct netlink_socket_t { + + /** + * Send a netlink message and wait for a reply. + * + * @param in netlink message to send + * @param out received netlink message + * @param out_len length of the received message + */ + status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in, + struct nlmsghdr **out, size_t *out_len); + + /** + * Send a netlink message and wait for its acknowledge. + * + * @param in netlink message to send + */ + status_t (*send_ack)(netlink_socket_t *this, struct nlmsghdr *in); + + /** + * Destroy the socket. + */ + void (*destroy)(netlink_socket_t *this); +}; + +/** + * Create a netlink_socket_t object. + * + * @param protocol protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE) + * @param names optional enum names for Netlink messages + * @param parallel support parallel queries on this Netlink socket + */ +netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, + bool parallel); + +/** + * Creates an rtattr and adds it to the given netlink message. + * + * @param hdr netlink message + * @param rta_type type of the rtattr + * @param data data to add to the rtattr + * @param buflen length of the netlink message buffer + */ +void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, + size_t buflen); + +/** + * Reserve space in a netlink message for given size and type, returning buffer. + * + * @param hdr netlink message + * @param buflen size of full netlink buffer + * @param type RTA type + * @param len length of RTA data + * @return buffer to len bytes of attribute data, NULL on error + */ +void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len); + +#endif /* KERNEL_NETLINK_SHARED_H_ */ diff --git a/src/libcharon/plugins/kernel_netlink/suites/test_socket.c b/src/libcharon/plugins/kernel_netlink/suites/test_socket.c new file mode 100644 index 000000000..3e8facd0a --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/suites/test_socket.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +#include + +#include "../kernel_netlink_shared.h" + +/** + * Netlink message drop configuration + */ +static int drop_interval = 0; + +/** + * Netlink message drop hook + */ +bool netlink_msg_loss(struct nlmsghdr *hdr) +{ + static refcount_t i; + + if (drop_interval) + { + return ref_get(&i) % drop_interval == drop_interval - 1; + } + return FALSE; +} + +START_TEST(test_echo) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtmsg *msg; + char dst[] = { + 127,0,0,1 + }; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_type = RTM_GETROUTE, + }, + }; + + msg = NLMSG_DATA(&request.hdr); + msg->rtm_family = AF_INET; + netlink_add_attribute(&request.hdr, RTA_DST, + chunk_from_thing(dst), sizeof(request)); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE); + free(out); + s->destroy(s); +} +END_TEST + +START_TEST(test_echo_dump) +{ + netlink_socket_t *s; + struct nlmsghdr *out, *current; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + current = out; + while (TRUE) + { + ck_assert(NLMSG_OK(current, len)); + if (current->nlmsg_type == NLMSG_DONE) + { + break; + } + ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK); + current = NLMSG_NEXT(current, len); + } + free(out); + s->destroy(s); +} +END_TEST + +CALLBACK(stress, void*, + netlink_socket_t *s) +{ + struct nlmsghdr *out; + struct rtmsg *msg; + char dst[] = { + 127,0,0,1 + }; + size_t len; + int i; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_type = RTM_GETROUTE, + }, + }; + + for (i = 0; i < 10; i++) + { + msg = NLMSG_DATA(&request.hdr); + msg->rtm_family = AF_INET; + netlink_add_attribute(&request.hdr, RTA_DST, + chunk_from_thing(dst), sizeof(request)); + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE); + free(out); + } + return NULL; +} + +CALLBACK(stress_dump, void*, + netlink_socket_t *s) +{ + struct nlmsghdr *out, *current; + struct rtgenmsg *msg; + size_t len; + int i; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + for (i = 0; i < 10; i++) + { + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + current = out; + while (TRUE) + { + ck_assert(NLMSG_OK(current, len)); + if (current->nlmsg_type == NLMSG_DONE) + { + break; + } + ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK); + current = NLMSG_NEXT(current, len); + } + free(out); + } + return NULL; +} + +START_TEST(test_stress) +{ + thread_t *threads[10]; + netlink_socket_t *s; + int i; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + for (i = 0; i < countof(threads); i++) + { + threads[i] = thread_create(stress, s); + } + for (i = 0; i < countof(threads); i++) + { + threads[i]->join(threads[i]); + } + s->destroy(s); +} +END_TEST + +START_TEST(test_stress_dump) +{ + thread_t *threads[10]; + netlink_socket_t *s; + int i; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + for (i = 0; i < countof(threads); i++) + { + threads[i] = thread_create(stress_dump, s); + } + for (i = 0; i < countof(threads); i++) + { + threads[i]->join(threads[i]); + } + s->destroy(s); +} +END_TEST + +START_TEST(test_retransmit_success) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + drop_interval = 2; + + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.timeout", 100, lib->ns); + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.retries", 1, lib->ns); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + free(out); + s->destroy(s); + + drop_interval = 0; +} +END_TEST + +START_TEST(test_retransmit_fail) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + drop_interval = 1; + + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.timeout", 50, lib->ns); + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.retries", 3, lib->ns); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == OUT_OF_RES); + s->destroy(s); + + drop_interval = 0; +} +END_TEST + +Suite *socket_suite_create() +{ + Suite *s; + TCase *tc; + + s = suite_create("netlink socket"); + + tc = tcase_create("echo"); + tcase_add_loop_test(tc, test_echo, 0, 2); + tcase_add_loop_test(tc, test_echo_dump, 0, 2); + suite_add_tcase(s, tc); + + tc = tcase_create("stress"); + tcase_add_loop_test(tc, test_stress, 0, 2); + tcase_add_loop_test(tc, test_stress_dump, 0, 2); + suite_add_tcase(s, tc); + + tc = tcase_create("retransmit"); + tcase_add_loop_test(tc, test_retransmit_success, 0, 2); + tcase_add_loop_test(tc, test_retransmit_fail, 0, 2); + suite_add_tcase(s, tc); + + return s; +} diff --git a/src/libcharon/plugins/kernel_netlink/tests.c b/src/libcharon/plugins/kernel_netlink/tests.c new file mode 100644 index 000000000..a1799ea70 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/tests.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +/* declare test suite constructors */ +#define TEST_SUITE(x) test_suite_t* x(); +#include "tests.h" +#undef TEST_SUITE + +static test_configuration_t tests[] = { +#define TEST_SUITE(x) \ + { .suite = x, }, +#include "tests.h" + { .suite = NULL, } +}; + +static bool test_runner_init(bool init) +{ + if (init) + { + lib->processor->set_threads(lib->processor, 8); + } + else + { + lib->processor->set_threads(lib->processor, 0); + lib->processor->cancel(lib->processor); + } + return TRUE; +} + +int main(int argc, char *argv[]) +{ + return test_runner_run("kernel-netlink", tests, test_runner_init); +} diff --git a/src/libcharon/plugins/kernel_netlink/tests.h b/src/libcharon/plugins/kernel_netlink/tests.h new file mode 100644 index 000000000..2b6715a78 --- /dev/null +++ b/src/libcharon/plugins/kernel_netlink/tests.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +TEST_SUITE(socket_suite_create) diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.am b/src/libcharon/plugins/kernel_pfkey/Makefile.am new file mode 100644 index 000000000..8fdca93a5 --- /dev/null +++ b/src/libcharon/plugins/kernel_pfkey/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la +else +plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la +endif + +libstrongswan_kernel_pfkey_la_SOURCES = \ + kernel_pfkey_plugin.h kernel_pfkey_plugin.c \ + kernel_pfkey_ipsec.h kernel_pfkey_ipsec.c + +libstrongswan_kernel_pfkey_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in new file mode 100644 index 000000000..f2876a272 --- /dev/null +++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in @@ -0,0 +1,782 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/kernel_pfkey +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_kernel_pfkey_la_LIBADD = +am_libstrongswan_kernel_pfkey_la_OBJECTS = kernel_pfkey_plugin.lo \ + kernel_pfkey_ipsec.lo +libstrongswan_kernel_pfkey_la_OBJECTS = \ + $(am_libstrongswan_kernel_pfkey_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_kernel_pfkey_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfkey_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfkey_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES) +DIST_SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-kernel-pfkey.la: $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfkey_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_kernel_pfkey_la_LINK) $(am_libstrongswan_kernel_pfkey_la_rpath) $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@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@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pluginLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c new file mode 100644 index 000000000..d505f1c33 --- /dev/null +++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -0,0 +1,3094 @@ +/* + * Copyright (C) 2008-2015 Tobias Brunner + * Copyright (C) 2008 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +/* + * Copyright (C) 2014 Nanoteq Pty Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#ifdef __FreeBSD__ +#include /* for LONG_MAX */ +#endif + +#ifdef HAVE_NET_PFKEYV2_H +#include +#else +#include +#endif + +#ifdef SADB_X_EXT_NAT_T_TYPE +#define HAVE_NATT +#endif + +#ifdef HAVE_NETIPSEC_IPSEC_H +#include +#elif defined(HAVE_NETINET6_IPSEC_H) +#include +#else +#include +#endif + +#ifdef HAVE_NATT +#ifdef HAVE_LINUX_UDP_H +#include +#else +#include +#endif /*HAVE_LINUX_UDP_H*/ +#endif /*HAVE_NATT*/ + +#include +#include +#include +#ifdef __APPLE__ +#include +#endif + +#include "kernel_pfkey_ipsec.h" + +#include +#include +#include +#include +#include +#include + +/** non linux specific */ +#ifndef IPPROTO_COMP +#ifdef IPPROTO_IPCOMP +#define IPPROTO_COMP IPPROTO_IPCOMP +#endif +#endif + +#ifndef SADB_X_AALG_SHA2_256HMAC +#define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256 +#define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384 +#define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512 +#endif + +#ifndef SADB_X_EALG_AESCBC +#define SADB_X_EALG_AESCBC SADB_X_EALG_AES +#endif + +#ifndef SADB_X_EALG_CASTCBC +#define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC +#endif + +#if !defined(SADB_X_EALG_AES_GCM_ICV8) && defined(SADB_X_EALG_AESGCM8) +#define SADB_X_EALG_AES_GCM_ICV8 SADB_X_EALG_AESGCM8 +#define SADB_X_EALG_AES_GCM_ICV12 SADB_X_EALG_AESGCM12 +#define SADB_X_EALG_AES_GCM_ICV16 SADB_X_EALG_AESGCM16 +#endif + +#ifndef SOL_IP +#define SOL_IP IPPROTO_IP +#define SOL_IPV6 IPPROTO_IPV6 +#endif + +/** from linux/in.h */ +#ifndef IP_IPSEC_POLICY +#define IP_IPSEC_POLICY 16 +#endif + +/** missing on uclibc */ +#ifndef IPV6_IPSEC_POLICY +#define IPV6_IPSEC_POLICY 34 +#endif + +/* from linux/udp.h */ +#ifndef UDP_ENCAP +#define UDP_ENCAP 100 +#endif + +#ifndef UDP_ENCAP_ESPINUDP +#define UDP_ENCAP_ESPINUDP 2 +#endif + +/* this is not defined on some platforms */ +#ifndef SOL_UDP +#define SOL_UDP IPPROTO_UDP +#endif + +/** base priority for installed policies */ +#define PRIO_BASE 384 + +#ifdef __APPLE__ +/** from xnu/bsd/net/pfkeyv2.h */ +#define SADB_X_EXT_NATT 0x002 + struct sadb_sa_2 { + struct sadb_sa sa; + u_int16_t sadb_sa_natt_port; + u_int16_t sadb_reserved0; + u_int32_t sadb_reserved1; + }; +#endif + +/** buffer size for PF_KEY messages */ +#define PFKEY_BUFFER_SIZE 4096 + +/** PF_KEY messages are 64 bit aligned */ +#define PFKEY_ALIGNMENT 8 +/** aligns len to 64 bits */ +#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1)) +/** calculates the properly padded length in 64 bit chunks */ +#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT)) +/** calculates user mode length i.e. in bytes */ +#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT) + +/** given a PF_KEY message header and an extension this updates the length in the header */ +#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len) +/** given a PF_KEY message header this returns a pointer to the next extension */ +#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len))) +/** copy an extension and append it to a PF_KEY message */ +#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))) +/** given a PF_KEY extension this returns a pointer to the next extension */ +#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))) +/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */ +#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext)) +/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */ +#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \ + (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \ + (ext)->sadb_ext_len <= (len)) + +typedef struct private_kernel_pfkey_ipsec_t private_kernel_pfkey_ipsec_t; + +/** + * Private variables and functions of kernel_pfkey class. + */ +struct private_kernel_pfkey_ipsec_t +{ + /** + * Public part of the kernel_pfkey_t object. + */ + kernel_pfkey_ipsec_t public; + + /** + * mutex to lock access to various lists + */ + mutex_t *mutex; + + /** + * List of installed policies (policy_entry_t) + */ + linked_list_t *policies; + + /** + * List of exclude routes (exclude_route_t) + */ + linked_list_t *excludes; + + /** + * Hash table of IPsec SAs using policies (ipsec_sa_t) + */ + hashtable_t *sas; + + /** + * whether to install routes along policies + */ + bool install_routes; + + /** + * mutex to lock access to the PF_KEY socket + */ + mutex_t *mutex_pfkey; + + /** + * PF_KEY socket to communicate with the kernel + */ + int socket; + + /** + * PF_KEY socket to receive acquire and expire events + */ + int socket_events; + + /** + * sequence number for messages sent to the kernel + */ + int seq; +}; + +typedef struct exclude_route_t exclude_route_t; + +/** + * Exclude route definition + */ +struct exclude_route_t { + /** destination address of exclude */ + host_t *dst; + /** source address for route */ + host_t *src; + /** nexthop exclude has been installed */ + host_t *gtw; + /** references to this route */ + int refs; +}; + +/** + * clean up a route exclude entry + */ +static void exclude_route_destroy(exclude_route_t *this) +{ + this->dst->destroy(this->dst); + this->src->destroy(this->src); + this->gtw->destroy(this->gtw); + free(this); +} + +typedef struct route_entry_t route_entry_t; + +/** + * installed routing entry + */ +struct route_entry_t { + /** name of the interface the route is bound to */ + char *if_name; + + /** source ip of the route */ + host_t *src_ip; + + /** gateway for this route */ + host_t *gateway; + + /** destination net */ + chunk_t dst_net; + + /** destination net prefixlen */ + u_int8_t prefixlen; + + /** reference to exclude route, if any */ + exclude_route_t *exclude; +}; + +/** + * destroy an route_entry_t object + */ +static void route_entry_destroy(route_entry_t *this) +{ + free(this->if_name); + DESTROY_IF(this->src_ip); + DESTROY_IF(this->gateway); + chunk_free(&this->dst_net); + free(this); +} + +/** + * compare two route_entry_t objects + */ +static bool route_entry_equals(route_entry_t *a, route_entry_t *b) +{ + return a->if_name && b->if_name && streq(a->if_name, b->if_name) && + a->src_ip->ip_equals(a->src_ip, b->src_ip) && + a->gateway && b->gateway && + a->gateway->ip_equals(a->gateway, b->gateway) && + chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen; +} + +typedef struct ipsec_sa_t ipsec_sa_t; + +/** + * IPsec SA assigned to a policy. + */ +struct ipsec_sa_t { + /** Source address of this SA */ + host_t *src; + + /** Destination address of this SA */ + host_t *dst; + + /** Description of this SA */ + ipsec_sa_cfg_t cfg; + + /** Reference count for this SA */ + refcount_t refcount; +}; + +/** + * Hash function for ipsec_sa_t objects + */ +static u_int ipsec_sa_hash(ipsec_sa_t *sa) +{ + return chunk_hash_inc(sa->src->get_address(sa->src), + chunk_hash_inc(sa->dst->get_address(sa->dst), + chunk_hash(chunk_from_thing(sa->cfg)))); +} + +/** + * Equality function for ipsec_sa_t objects + */ +static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa) +{ + return sa->src->ip_equals(sa->src, other_sa->src) && + sa->dst->ip_equals(sa->dst, other_sa->dst) && + memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t)); +} + +/** + * Allocate or reference an IPsec SA object + */ +static ipsec_sa_t *ipsec_sa_create(private_kernel_pfkey_ipsec_t *this, + host_t *src, host_t *dst, + ipsec_sa_cfg_t *cfg) +{ + ipsec_sa_t *sa, *found; + INIT(sa, + .src = src, + .dst = dst, + .cfg = *cfg, + ); + found = this->sas->get(this->sas, sa); + if (!found) + { + sa->src = src->clone(src); + sa->dst = dst->clone(dst); + this->sas->put(this->sas, sa, sa); + } + else + { + free(sa); + sa = found; + } + ref_get(&sa->refcount); + return sa; +} + +/** + * Release and destroy an IPsec SA object + */ +static void ipsec_sa_destroy(private_kernel_pfkey_ipsec_t *this, + ipsec_sa_t *sa) +{ + if (ref_put(&sa->refcount)) + { + this->sas->remove(this->sas, sa); + DESTROY_IF(sa->src); + DESTROY_IF(sa->dst); + free(sa); + } +} + +typedef struct policy_sa_t policy_sa_t; +typedef struct policy_sa_in_t policy_sa_in_t; + +/** + * Mapping between a policy and an IPsec SA. + */ +struct policy_sa_t { + /** Priority assigned to the policy when installed with this SA */ + u_int32_t priority; + + /** Type of the policy */ + policy_type_t type; + + /** Assigned SA */ + ipsec_sa_t *sa; +}; + +/** + * For input policies we also cache the traffic selectors in order to install + * the route. + */ +struct policy_sa_in_t { + /** Generic interface */ + policy_sa_t generic; + + /** Source traffic selector of this policy */ + traffic_selector_t *src_ts; + + /** Destination traffic selector of this policy */ + traffic_selector_t *dst_ts; +}; + +/** + * Create a policy_sa(_in)_t object + */ +static policy_sa_t *policy_sa_create(private_kernel_pfkey_ipsec_t *this, + policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, ipsec_sa_cfg_t *cfg) +{ + policy_sa_t *policy; + + if (dir == POLICY_IN) + { + policy_sa_in_t *in; + INIT(in, + .src_ts = src_ts->clone(src_ts), + .dst_ts = dst_ts->clone(dst_ts), + ); + policy = &in->generic; + } + else + { + INIT(policy, .priority = 0); + } + policy->type = type; + policy->sa = ipsec_sa_create(this, src, dst, cfg); + return policy; +} + +/** + * Destroy a policy_sa(_in)_t object + */ +static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir, + private_kernel_pfkey_ipsec_t *this) +{ + if (*dir == POLICY_IN) + { + policy_sa_in_t *in = (policy_sa_in_t*)policy; + in->src_ts->destroy(in->src_ts); + in->dst_ts->destroy(in->dst_ts); + } + ipsec_sa_destroy(this, policy->sa); + free(policy); +} + +typedef struct policy_entry_t policy_entry_t; + +/** + * installed kernel policy. + */ +struct policy_entry_t { + /** Index assigned by the kernel */ + u_int32_t index; + + /** Direction of this policy: in, out, forward */ + u_int8_t direction; + + /** Parameters of installed policy */ + struct { + /** Subnet and port */ + host_t *net; + /** Subnet mask */ + u_int8_t mask; + /** Protocol */ + u_int8_t proto; + } src, dst; + + /** Associated route installed for this policy */ + route_entry_t *route; + + /** List of SAs this policy is used by, ordered by priority */ + linked_list_t *used_by; +}; + +/** + * Create a policy_entry_t object + */ +static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t dir) +{ + policy_entry_t *policy; + INIT(policy, + .direction = dir, + ); + u_int16_t port; + u_int8_t proto; + + src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask); + dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask); + + /* src or dest proto may be "any" (0), use more restrictive one */ + proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts)); + /* map the ports to ICMP type/code how the Linux kernel expects them, that + * is, type in src, code in dst */ + if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) + { + port = max(policy->src.net->get_port(policy->src.net), + policy->dst.net->get_port(policy->dst.net)); + policy->src.net->set_port(policy->src.net, + traffic_selector_icmp_type(port)); + policy->dst.net->set_port(policy->dst.net, + traffic_selector_icmp_code(port)); + } + else if (!proto) + { + proto = IPSEC_PROTO_ANY; + } + policy->src.proto = policy->dst.proto = proto; + + return policy; +} + +/** + * Destroy a policy_entry_t object + */ +static void policy_entry_destroy(policy_entry_t *policy, + private_kernel_pfkey_ipsec_t *this) +{ + if (policy->route) + { + route_entry_destroy(policy->route); + } + if (policy->used_by) + { + policy->used_by->invoke_function(policy->used_by, + (linked_list_invoke_t)policy_sa_destroy, + &policy->direction, this); + policy->used_by->destroy(policy->used_by); + } + DESTROY_IF(policy->src.net); + DESTROY_IF(policy->dst.net); + free(policy); +} + +/** + * compares two policy_entry_t + */ +static inline bool policy_entry_equals(policy_entry_t *current, + policy_entry_t *policy) +{ + return current->direction == policy->direction && + current->src.proto == policy->src.proto && + current->dst.proto == policy->dst.proto && + current->src.mask == policy->src.mask && + current->dst.mask == policy->dst.mask && + current->src.net->equals(current->src.net, policy->src.net) && + current->dst.net->equals(current->dst.net, policy->dst.net); +} + +/** + * compare the given kernel index with that of a policy + */ +static inline bool policy_entry_match_byindex(policy_entry_t *current, + u_int32_t *index) +{ + return current->index == *index; +} + +/** + * Calculate the priority of a policy + */ +static inline u_int32_t get_priority(policy_entry_t *policy, + policy_priority_t prio) +{ + u_int32_t priority = PRIO_BASE; + switch (prio) + { + case POLICY_PRIORITY_FALLBACK: + priority <<= 1; + /* fall-through */ + case POLICY_PRIORITY_ROUTED: + priority <<= 1; + /* fall-through */ + case POLICY_PRIORITY_DEFAULT: + priority <<= 1; + /* fall-trough */ + case POLICY_PRIORITY_PASS: + break; + } + /* calculate priority based on selector size, small size = high prio */ + priority -= policy->src.mask; + priority -= policy->dst.mask; + priority <<= 2; /* make some room for the two flags */ + priority += policy->src.net->get_port(policy->src.net) || + policy->dst.net->get_port(policy->dst.net) ? + 0 : 2; + priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1; + return priority; +} + +typedef struct pfkey_msg_t pfkey_msg_t; + +struct pfkey_msg_t +{ + /** + * PF_KEY message base + */ + struct sadb_msg *msg; + + /** + * PF_KEY message extensions + */ + union { + struct sadb_ext *ext[SADB_EXT_MAX + 1]; + struct { + struct sadb_ext *reserved; /* SADB_EXT_RESERVED */ + struct sadb_sa *sa; /* SADB_EXT_SA */ + struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */ + struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */ + struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */ + struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */ + struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */ + struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */ + struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */ + struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */ + struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */ + struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */ + struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */ + struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */ + struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */ + struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */ + struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */ + struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */ + struct sadb_x_policy *x_policy; /* SADB_X_EXT_POLICY */ + struct sadb_x_sa2 *x_sa2; /* SADB_X_EXT_SA2 */ + struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */ + struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */ + struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */ + struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */ + struct sadb_x_sec_ctx *x_sec_ctx; /* SADB_X_EXT_SEC_CTX */ + struct sadb_x_kmaddress *x_kmaddress; /* SADB_X_EXT_KMADDRESS */ + } __attribute__((__packed__)); + }; +}; + +ENUM(sadb_ext_type_names, SADB_EXT_RESERVED, SADB_EXT_MAX, + "SADB_EXT_RESERVED", + "SADB_EXT_SA", + "SADB_EXT_LIFETIME_CURRENT", + "SADB_EXT_LIFETIME_HARD", + "SADB_EXT_LIFETIME_SOFT", + "SADB_EXT_ADDRESS_SRC", + "SADB_EXT_ADDRESS_DST", + "SADB_EXT_ADDRESS_PROXY", + "SADB_EXT_KEY_AUTH", + "SADB_EXT_KEY_ENCRYPT", + "SADB_EXT_IDENTITY_SRC", + "SADB_EXT_IDENTITY_DST", + "SADB_EXT_SENSITIVITY", + "SADB_EXT_PROPOSAL", + "SADB_EXT_SUPPORTED_AUTH", + "SADB_EXT_SUPPORTED_ENCRYPT", + "SADB_EXT_SPIRANGE", + "SADB_X_EXT_KMPRIVATE", + "SADB_X_EXT_POLICY", + "SADB_X_EXT_SA2", + "SADB_X_EXT_NAT_T_TYPE", + "SADB_X_EXT_NAT_T_SPORT", + "SADB_X_EXT_NAT_T_DPORT", + "SADB_X_EXT_NAT_T_OA", + "SADB_X_EXT_SEC_CTX", + "SADB_X_EXT_KMADDRESS" +); + +/** + * convert a protocol identifier to the PF_KEY sa type + */ +static u_int8_t proto2satype(u_int8_t proto) +{ + switch (proto) + { + case IPPROTO_ESP: + return SADB_SATYPE_ESP; + case IPPROTO_AH: + return SADB_SATYPE_AH; + case IPPROTO_COMP: + return SADB_X_SATYPE_IPCOMP; + default: + return proto; + } +} + +/** + * convert a PF_KEY sa type to a protocol identifier + */ +static u_int8_t satype2proto(u_int8_t satype) +{ + switch (satype) + { + case SADB_SATYPE_ESP: + return IPPROTO_ESP; + case SADB_SATYPE_AH: + return IPPROTO_AH; + case SADB_X_SATYPE_IPCOMP: + return IPPROTO_COMP; + default: + return satype; + } +} + +/** + * convert the general ipsec mode to the one defined in ipsec.h + */ +static u_int8_t mode2kernel(ipsec_mode_t mode) +{ + switch (mode) + { + case MODE_TRANSPORT: + return IPSEC_MODE_TRANSPORT; + case MODE_TUNNEL: + return IPSEC_MODE_TUNNEL; +#ifdef HAVE_IPSEC_MODE_BEET + case MODE_BEET: + return IPSEC_MODE_BEET; +#endif + default: + return mode; + } +} + +/** + * convert the general policy direction to the one defined in ipsec.h + */ +static u_int8_t dir2kernel(policy_dir_t dir) +{ + switch (dir) + { + case POLICY_IN: + return IPSEC_DIR_INBOUND; + case POLICY_OUT: + return IPSEC_DIR_OUTBOUND; +#ifdef HAVE_IPSEC_DIR_FWD + case POLICY_FWD: + return IPSEC_DIR_FWD; +#endif + default: + return IPSEC_DIR_INVALID; + } +} + +/** + * convert the policy type to the one defined in ipsec.h + */ +static inline u_int16_t type2kernel(policy_type_t type) +{ + switch (type) + { + case POLICY_IPSEC: + return IPSEC_POLICY_IPSEC; + case POLICY_PASS: + return IPSEC_POLICY_NONE; + case POLICY_DROP: + return IPSEC_POLICY_DISCARD; + } + return type; +} + +#ifdef SADB_X_MIGRATE +/** + * convert the policy direction in ipsec.h to the general one. + */ +static policy_dir_t kernel2dir(u_int8_t dir) +{ + switch (dir) + { + case IPSEC_DIR_INBOUND: + return POLICY_IN; + case IPSEC_DIR_OUTBOUND: + return POLICY_OUT; +#ifdef HAVE_IPSEC_DIR_FWD + case IPSEC_DIR_FWD: + return POLICY_FWD; +#endif + default: + return dir; + } +} +#endif /*SADB_X_MIGRATE*/ + +typedef struct kernel_algorithm_t kernel_algorithm_t; + +/** + * Mapping of IKEv2 algorithms to PF_KEY algorithms + */ +struct kernel_algorithm_t { + /** + * Identifier specified in IKEv2 + */ + int ikev2; + + /** + * Identifier as defined in pfkeyv2.h + */ + int kernel; +}; + +#define END_OF_LIST -1 + +/** + * Algorithms for encryption + */ +static kernel_algorithm_t encryption_algs[] = { +/* {ENCR_DES_IV64, 0 }, */ + {ENCR_DES, SADB_EALG_DESCBC }, + {ENCR_3DES, SADB_EALG_3DESCBC }, +/* {ENCR_RC5, 0 }, */ +/* {ENCR_IDEA, 0 }, */ + {ENCR_CAST, SADB_X_EALG_CASTCBC }, + {ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC }, +/* {ENCR_3IDEA, 0 }, */ +/* {ENCR_DES_IV32, 0 }, */ + {ENCR_NULL, SADB_EALG_NULL }, + {ENCR_AES_CBC, SADB_X_EALG_AESCBC }, +#ifdef SADB_X_EALG_AESCTR + {ENCR_AES_CTR, SADB_X_EALG_AESCTR }, +#endif +/* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */ +/* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */ +/* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */ +#ifdef SADB_X_EALG_AES_GCM_ICV8 /* assume the others are defined too */ + {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 }, + {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 }, + {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 }, +#endif +#ifdef SADB_X_EALG_CAMELLIACBC + {ENCR_CAMELLIA_CBC, SADB_X_EALG_CAMELLIACBC }, +#endif + {END_OF_LIST, 0 }, +}; + +/** + * Algorithms for integrity protection + */ +static kernel_algorithm_t integrity_algs[] = { + {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC }, + {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC }, + {AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC }, + {AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC }, + {AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC }, +/* {AUTH_DES_MAC, 0, }, */ +/* {AUTH_KPDK_MD5, 0, }, */ +#ifdef SADB_X_AALG_AES_XCBC_MAC + {AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, }, +#endif + {END_OF_LIST, 0, }, +}; + +/** + * Algorithms for IPComp, unused yet + */ +static kernel_algorithm_t compression_algs[] = { +/* {IPCOMP_OUI, 0 }, */ + {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE }, +#ifdef SADB_X_CALG_LZS + {IPCOMP_LZS, SADB_X_CALG_LZS }, +#endif +#ifdef SADB_X_CALG_LZJH + {IPCOMP_LZJH, SADB_X_CALG_LZJH }, +#endif + {END_OF_LIST, 0 }, +}; + +/** + * Look up a kernel algorithm ID and its key size + */ +static int lookup_algorithm(transform_type_t type, int ikev2) +{ + kernel_algorithm_t *list; + u_int16_t alg = 0; + + switch (type) + { + case ENCRYPTION_ALGORITHM: + list = encryption_algs; + break; + case INTEGRITY_ALGORITHM: + list = integrity_algs; + break; + case COMPRESSION_ALGORITHM: + list = compression_algs; + break; + default: + return 0; + } + while (list->ikev2 != END_OF_LIST) + { + if (ikev2 == list->ikev2) + { + return list->kernel; + } + list++; + } + charon->kernel->lookup_algorithm(charon->kernel, ikev2, type, &alg, NULL); + return alg; +} + +/** + * Helper to set a port in a sockaddr_t, the port has to be in host order + */ +static void set_port(sockaddr_t *addr, u_int16_t port) +{ + switch (addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in*)addr; + sin->sin_port = htons(port); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr; + sin6->sin6_port = htons(port); + break; + } + } +} + +/** + * Copy a host_t as sockaddr_t to the given memory location. + * @return the number of bytes copied + */ +static size_t hostcpy(void *dest, host_t *host, bool include_port) +{ + sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest; + socklen_t *len = host->get_sockaddr_len(host); + + memcpy(dest, addr, *len); +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + dest_addr->sa_len = *len; +#endif + if (!include_port) + { + set_port(dest_addr, 0); + } + return *len; +} + +/** + * add a host to the given sadb_msg + */ +static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type, + u_int8_t proto, u_int8_t prefixlen, bool include_port) +{ + struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg); + size_t len; + + addr->sadb_address_exttype = type; + addr->sadb_address_proto = proto; + addr->sadb_address_prefixlen = prefixlen; + len = hostcpy(addr + 1, host, include_port); + addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len); + PFKEY_EXT_ADD(msg, addr); +} + +/** + * adds an empty address extension to the given sadb_msg + */ +static void add_anyaddr_ext(struct sadb_msg *msg, int family, u_int8_t type) +{ + socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); + struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg); + addr->sadb_address_exttype = type; + sockaddr_t *saddr = (sockaddr_t*)(addr + 1); + saddr->sa_family = family; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + saddr->sa_len = len; +#endif + addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len); + PFKEY_EXT_ADD(msg, addr); +} + +#ifdef HAVE_NATT +/** + * add udp encap extensions to a sadb_msg + */ +static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst) +{ + struct sadb_x_nat_t_type* nat_type; + struct sadb_x_nat_t_port* nat_port; + + nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg); + nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; + nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(*nat_type)); + nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP; + PFKEY_EXT_ADD(msg, nat_type); + + nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg); + nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT; + nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(*nat_port)); + nat_port->sadb_x_nat_t_port_port = htons(src->get_port(src)); + PFKEY_EXT_ADD(msg, nat_port); + + nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg); + nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT; + nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(*nat_port)); + nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst)); + PFKEY_EXT_ADD(msg, nat_port); +} +#endif /*HAVE_NATT*/ + +/** + * Convert a sadb_address to a traffic_selector + */ +static traffic_selector_t* sadb_address2ts(struct sadb_address *address) +{ + traffic_selector_t *ts; + host_t *host; + u_int8_t proto; + + proto = address->sadb_address_proto; + proto = proto == IPSEC_PROTO_ANY ? 0 : proto; + + /* The Linux 2.6 kernel does not set the protocol and port information + * in the src and dst sadb_address extensions of the SADB_ACQUIRE message. + */ + host = host_create_from_sockaddr((sockaddr_t*)&address[1]); + ts = traffic_selector_create_from_subnet(host, + address->sadb_address_prefixlen, + proto, host->get_port(host), + host->get_port(host) ?: 65535); + return ts; +} + +/** + * Parses a pfkey message received from the kernel + */ +static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out) +{ + struct sadb_ext* ext; + size_t len; + + memset(out, 0, sizeof(pfkey_msg_t)); + out->msg = msg; + + len = msg->sadb_msg_len; + len -= PFKEY_LEN(sizeof(struct sadb_msg)); + + ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg)); + + while (len >= PFKEY_LEN(sizeof(struct sadb_ext))) + { + DBG3(DBG_KNL, " %N", sadb_ext_type_names, ext->sadb_ext_type); + if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) || + ext->sadb_ext_len > len) + { + DBG1(DBG_KNL, "length of %N extension is invalid", + sadb_ext_type_names, ext->sadb_ext_type); + break; + } + + if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type)) + { + DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", + ext->sadb_ext_type); + break; + } + + if (out->ext[ext->sadb_ext_type]) + { + DBG1(DBG_KNL, "duplicate %N extension", + sadb_ext_type_names, ext->sadb_ext_type); + break; + } + + out->ext[ext->sadb_ext_type] = ext; + ext = PFKEY_EXT_NEXT_LEN(ext, len); + } + + if (len) + { + DBG1(DBG_KNL, "PF_KEY message length is invalid"); + return FAILED; + } + + return SUCCESS; +} + +/** + * Send a message to a specific PF_KEY socket and handle the response. + */ +static status_t pfkey_send_socket(private_kernel_pfkey_ipsec_t *this, int socket, + struct sadb_msg *in, struct sadb_msg **out, size_t *out_len) +{ + unsigned char buf[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg; + int in_len, len; + + this->mutex_pfkey->lock(this->mutex_pfkey); + + /* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367, + * in particular the behavior in response to an SADB_ACQUIRE. */ + in->sadb_msg_seq = ++this->seq; + in->sadb_msg_pid = getpid(); + + in_len = PFKEY_USER_LEN(in->sadb_msg_len); + + while (TRUE) + { + len = send(socket, in, in_len, 0); + + if (len != in_len) + { + if (errno == EINTR) + { + /* interrupted, try again */ + continue; + } + this->mutex_pfkey->unlock(this->mutex_pfkey); + DBG1(DBG_KNL, "error sending to PF_KEY socket: %s", + strerror(errno)); + return FAILED; + } + break; + } + + while (TRUE) + { + msg = (struct sadb_msg*)buf; + + len = recv(socket, buf, sizeof(buf), 0); + + if (len < 0) + { + if (errno == EINTR) + { + DBG1(DBG_KNL, "got interrupted"); + /* interrupted, try again */ + continue; + } + DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", + strerror(errno)); + this->mutex_pfkey->unlock(this->mutex_pfkey); + return FAILED; + } + if (len < sizeof(struct sadb_msg) || + msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg))) + { + DBG1(DBG_KNL, "received corrupted PF_KEY message"); + this->mutex_pfkey->unlock(this->mutex_pfkey); + return FAILED; + } + if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT) + { + DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY " + "message"); + this->mutex_pfkey->unlock(this->mutex_pfkey); + return FAILED; + } + if (msg->sadb_msg_pid != in->sadb_msg_pid) + { + DBG2(DBG_KNL, "received PF_KEY message is not intended for us"); + continue; + } + if (msg->sadb_msg_seq != this->seq) + { + DBG2(DBG_KNL, "received PF_KEY message with unexpected sequence " + "number, was %d expected %d", msg->sadb_msg_seq, + this->seq); + if (msg->sadb_msg_seq == 0) + { + /* FreeBSD and Mac OS X do this for the response to + * SADB_X_SPDGET (but not for the response to SADB_GET). + * FreeBSD: 'key_spdget' in /usr/src/sys/netipsec/key.c. */ + } + else if (msg->sadb_msg_seq < this->seq) + { + continue; + } + else + { + this->mutex_pfkey->unlock(this->mutex_pfkey); + return FAILED; + } + } + if (msg->sadb_msg_type != in->sadb_msg_type) + { + DBG2(DBG_KNL, "received PF_KEY message of wrong type, " + "was %d expected %d, ignoring", msg->sadb_msg_type, + in->sadb_msg_type); + } + break; + } + + *out_len = len; + *out = (struct sadb_msg*)malloc(len); + memcpy(*out, buf, len); + + this->mutex_pfkey->unlock(this->mutex_pfkey); + return SUCCESS; +} + +/** + * Send a message to the default PF_KEY socket and handle the response. + */ +static status_t pfkey_send(private_kernel_pfkey_ipsec_t *this, + struct sadb_msg *in, struct sadb_msg **out, + size_t *out_len) +{ + return pfkey_send_socket(this, this->socket, in, out, out_len); +} + +/** + * Process a SADB_ACQUIRE message from the kernel + */ +static void process_acquire(private_kernel_pfkey_ipsec_t *this, + struct sadb_msg* msg) +{ + pfkey_msg_t response; + u_int32_t index, reqid = 0; + traffic_selector_t *src_ts, *dst_ts; + policy_entry_t *policy; + policy_sa_t *sa; + + switch (msg->sadb_msg_satype) + { + case SADB_SATYPE_UNSPEC: + case SADB_SATYPE_ESP: + case SADB_SATYPE_AH: + break; + default: + /* acquire for AH/ESP only */ + return; + } + DBG2(DBG_KNL, "received an SADB_ACQUIRE"); + + if (parse_pfkey_message(msg, &response) != SUCCESS) + { + DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed"); + return; + } + + index = response.x_policy->sadb_x_policy_id; + this->mutex->lock(this->mutex); + if (this->policies->find_first(this->policies, + (linked_list_match_t)policy_entry_match_byindex, + (void**)&policy, &index) == SUCCESS && + policy->used_by->get_first(policy->used_by, (void**)&sa) == SUCCESS) + { + reqid = sa->sa->cfg.reqid; + } + else + { + DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no " + "matching policy found", index); + } + this->mutex->unlock(this->mutex); + + src_ts = sadb_address2ts(response.src); + dst_ts = sadb_address2ts(response.dst); + + charon->kernel->acquire(charon->kernel, reqid, src_ts, dst_ts); +} + +/** + * Process a SADB_EXPIRE message from the kernel + */ +static void process_expire(private_kernel_pfkey_ipsec_t *this, + struct sadb_msg* msg) +{ + pfkey_msg_t response; + u_int8_t protocol; + u_int32_t spi; + host_t *dst; + bool hard; + + DBG2(DBG_KNL, "received an SADB_EXPIRE"); + + if (parse_pfkey_message(msg, &response) != SUCCESS) + { + DBG1(DBG_KNL, "parsing SADB_EXPIRE from kernel failed"); + return; + } + + protocol = satype2proto(msg->sadb_msg_satype); + spi = response.sa->sadb_sa_spi; + hard = response.lft_hard != NULL; + + if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH) + { + dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1)); + if (dst) + { + charon->kernel->expire(charon->kernel, protocol, spi, dst, hard); + dst->destroy(dst); + } + } +} + +#ifdef SADB_X_MIGRATE +/** + * Process a SADB_X_MIGRATE message from the kernel + */ +static void process_migrate(private_kernel_pfkey_ipsec_t *this, + struct sadb_msg* msg) +{ + pfkey_msg_t response; + traffic_selector_t *src_ts, *dst_ts; + policy_dir_t dir; + u_int32_t reqid = 0; + host_t *local = NULL, *remote = NULL; + + DBG2(DBG_KNL, "received an SADB_X_MIGRATE"); + + if (parse_pfkey_message(msg, &response) != SUCCESS) + { + DBG1(DBG_KNL, "parsing SADB_X_MIGRATE from kernel failed"); + return; + } + src_ts = sadb_address2ts(response.src); + dst_ts = sadb_address2ts(response.dst); + dir = kernel2dir(response.x_policy->sadb_x_policy_dir); + DBG2(DBG_KNL, " policy %R === %R %N, id %u", src_ts, dst_ts, + policy_dir_names, dir); + + /* SADB_X_EXT_KMADDRESS is not present in unpatched kernels < 2.6.28 */ + if (response.x_kmaddress) + { + sockaddr_t *local_addr, *remote_addr; + u_int32_t local_len; + + local_addr = (sockaddr_t*)&response.x_kmaddress[1]; + local = host_create_from_sockaddr(local_addr); + local_len = (local_addr->sa_family == AF_INET6)? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); + remote_addr = (sockaddr_t*)((u_int8_t*)local_addr + local_len); + remote = host_create_from_sockaddr(remote_addr); + DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote); + } + + if (src_ts && dst_ts && local && remote) + { + charon->kernel->migrate(charon->kernel, reqid, src_ts, dst_ts, dir, + local, remote); + } + else + { + DESTROY_IF(src_ts); + DESTROY_IF(dst_ts); + DESTROY_IF(local); + DESTROY_IF(remote); + } +} +#endif /*SADB_X_MIGRATE*/ + +#ifdef SADB_X_NAT_T_NEW_MAPPING +/** + * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel + */ +static void process_mapping(private_kernel_pfkey_ipsec_t *this, + struct sadb_msg* msg) +{ + pfkey_msg_t response; + u_int32_t spi; + sockaddr_t *sa; + host_t *dst, *new; + + DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING"); + + if (parse_pfkey_message(msg, &response) != SUCCESS) + { + DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed"); + return; + } + + if (!response.x_sa2) + { + DBG1(DBG_KNL, "received SADB_X_NAT_T_NEW_MAPPING is missing required " + "information"); + return; + } + + spi = response.sa->sadb_sa_spi; + + if (satype2proto(msg->sadb_msg_satype) != IPPROTO_ESP) + { + return; + } + + sa = (sockaddr_t*)(response.dst + 1); + dst = host_create_from_sockaddr(sa); + switch (sa->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in*)sa; + sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; + sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port); + break; + } + default: + break; + } + if (dst) + { + new = host_create_from_sockaddr(sa); + if (new) + { + charon->kernel->mapping(charon->kernel, IPPROTO_ESP, spi, dst, new); + new->destroy(new); + } + dst->destroy(dst); + } +} +#endif /*SADB_X_NAT_T_NEW_MAPPING*/ + +/** + * Receives events from kernel + */ +static bool receive_events(private_kernel_pfkey_ipsec_t *this, int fd, + watcher_event_t event) +{ + unsigned char buf[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg = (struct sadb_msg*)buf; + int len; + + len = recvfrom(this->socket_events, buf, sizeof(buf), MSG_DONTWAIT, NULL, 0); + if (len < 0) + { + switch (errno) + { + case EINTR: + /* interrupted, try again */ + return TRUE; + case EAGAIN: + /* no data ready, select again */ + return TRUE; + default: + DBG1(DBG_KNL, "unable to receive from PF_KEY event socket"); + sleep(1); + return TRUE; + } + } + + if (len < sizeof(struct sadb_msg) || + msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg))) + { + DBG2(DBG_KNL, "received corrupted PF_KEY message"); + return TRUE; + } + if (msg->sadb_msg_pid != 0) + { /* not from kernel. not interested, try another one */ + return TRUE; + } + if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT) + { + DBG1(DBG_KNL, "buffer was too small to receive the complete " + "PF_KEY message"); + return TRUE; + } + + switch (msg->sadb_msg_type) + { + case SADB_ACQUIRE: + process_acquire(this, msg); + break; + case SADB_EXPIRE: + process_expire(this, msg); + break; +#ifdef SADB_X_MIGRATE + case SADB_X_MIGRATE: + process_migrate(this, msg); + break; +#endif /*SADB_X_MIGRATE*/ +#ifdef SADB_X_NAT_T_NEW_MAPPING + case SADB_X_NAT_T_NEW_MAPPING: + process_mapping(this, msg); + break; +#endif /*SADB_X_NAT_T_NEW_MAPPING*/ + default: + break; + } + + return TRUE; +} + +/** + * Get an SPI for a specific protocol from the kernel. + */ + +static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, + host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max, + u_int32_t *spi) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_spirange *range; + pfkey_msg_t response; + u_int32_t received_spi = 0; + size_t len; + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_GETSPI; + msg->sadb_msg_satype = proto2satype(proto); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); + add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); + + range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg); + range->sadb_spirange_exttype = SADB_EXT_SPIRANGE; + range->sadb_spirange_len = PFKEY_LEN(sizeof(struct sadb_spirange)); + range->sadb_spirange_min = min; + range->sadb_spirange_max = max; + PFKEY_EXT_ADD(msg, range); + + if (pfkey_send(this, msg, &out, &len) == SUCCESS) + { + if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "allocating SPI failed: %s (%d)", + strerror(out->sadb_msg_errno), out->sadb_msg_errno); + } + else if (parse_pfkey_message(out, &response) == SUCCESS) + { + received_spi = response.sa->sadb_sa_spi; + } + free(out); + } + + if (received_spi == 0) + { + return FAILED; + } + + *spi = received_spi; + return SUCCESS; +} + +METHOD(kernel_ipsec_t, get_spi, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t *spi) +{ + if (get_spi_internal(this, src, dst, protocol, + 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get SPI"); + return FAILED; + } + + DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi)); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, get_cpi, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + u_int16_t *cpi) +{ + u_int32_t received_spi = 0; + + DBG2(DBG_KNL, "getting CPI"); + + if (get_spi_internal(this, src, dst, IPPROTO_COMP, + 0x100, 0xEFFF, &received_spi) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get CPI"); + return FAILED; + } + + *cpi = htons((u_int16_t)ntohl(received_spi)); + + DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi)); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, add_sa, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, + u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc, + lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, + u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_sa *sa; + struct sadb_x_sa2 *sa2; + struct sadb_lifetime *lft; + struct sadb_key *key; + size_t len; + + /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0 + * we are in the recursive call below */ + if (ipcomp != IPCOMP_NONE && cpi != 0) + { + lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}}; + add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, + tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, + chunk_empty, mode, ipcomp, 0, 0, FALSE, FALSE, FALSE, inbound, + update, NULL, NULL); + ipcomp = IPCOMP_NONE; + /* use transport mode ESP SA, IPComp uses tunnel mode */ + mode = MODE_TRANSPORT; + } + + if (update) + { + /* As we didn't know the reqid during SPI allocation, we used reqid + * zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we + * have to delete the SPI allocation state manually. The reqid + * selector does not count for that, therefore we have to delete + * that state before installing the new SA to avoid deleting the + * the new state after installing it. */ + mark_t zeromark = {0, 0}; + + if (this->public.interface.del_sa(&this->public.interface, + src, dst, spi, protocol, 0, zeromark) != SUCCESS) + { + DBG1(DBG_KNL, "deleting SPI allocation SA failed"); + } + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", + ntohl(spi), reqid); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_ADD; + msg->sadb_msg_satype = proto2satype(protocol); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + +#ifdef __APPLE__ + if (encap) + { + struct sadb_sa_2 *sa_2; + sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg); + sa_2->sadb_sa_natt_port = dst->get_port(dst); + sa = &sa_2->sa; + sa->sadb_sa_flags |= SADB_X_EXT_NATT; + len = sizeof(struct sadb_sa_2); + } + else +#endif + { + sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); + len = sizeof(struct sadb_sa); + } + sa->sadb_sa_exttype = SADB_EXT_SA; + sa->sadb_sa_len = PFKEY_LEN(len); + sa->sadb_sa_spi = spi; + if (protocol == IPPROTO_COMP) + { + sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp); + } + else + { + /* Linux interprets sadb_sa_replay as number of packets/bits in the + * replay window, whereas on BSD it's the size of the window in bytes */ +#ifdef __linux__ + sa->sadb_sa_replay = min(replay_window, 32); +#else + sa->sadb_sa_replay = (replay_window + 7) / 8; +#endif + sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg); + sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg); + } + PFKEY_EXT_ADD(msg, sa); + + sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); + sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; + sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange)); + sa2->sadb_x_sa2_mode = mode2kernel(mode); + sa2->sadb_x_sa2_reqid = reqid; + PFKEY_EXT_ADD(msg, sa2); + + add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); + add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); + + lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); + lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; + lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); + lft->sadb_lifetime_allocations = lifetime->packets.rekey; + lft->sadb_lifetime_bytes = lifetime->bytes.rekey; + lft->sadb_lifetime_addtime = lifetime->time.rekey; + lft->sadb_lifetime_usetime = 0; /* we only use addtime */ + PFKEY_EXT_ADD(msg, lft); + + lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); + lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; + lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); + lft->sadb_lifetime_allocations = lifetime->packets.life; + lft->sadb_lifetime_bytes = lifetime->bytes.life; + lft->sadb_lifetime_addtime = lifetime->time.life; + lft->sadb_lifetime_usetime = 0; /* we only use addtime */ + PFKEY_EXT_ADD(msg, lft); + + if (enc_alg != ENCR_UNDEFINED) + { + if (!sa->sadb_sa_encrypt) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + encryption_algorithm_names, enc_alg); + return FAILED; + } + DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", + encryption_algorithm_names, enc_alg, enc_key.len * 8); + + key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); + key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; + key->sadb_key_bits = enc_key.len * 8; + key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len); + memcpy(key + 1, enc_key.ptr, enc_key.len); + + PFKEY_EXT_ADD(msg, key); + } + + if (int_alg != AUTH_UNDEFINED) + { + if (!sa->sadb_sa_auth) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + integrity_algorithm_names, int_alg); + return FAILED; + } + DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", + integrity_algorithm_names, int_alg, int_key.len * 8); + + key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); + key->sadb_key_exttype = SADB_EXT_KEY_AUTH; + key->sadb_key_bits = int_key.len * 8; + key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len); + memcpy(key + 1, int_key.ptr, int_key.len); + + PFKEY_EXT_ADD(msg, key); + } + +#ifdef HAVE_NATT + if (encap) + { + add_encap_ext(msg, src, dst); + } +#endif /*HAVE_NATT*/ + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)", + ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); + free(out); + return FAILED; + } + + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, update_sa, status_t, + private_kernel_pfkey_ipsec_t *this, u_int32_t spi, u_int8_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, + bool encap, bool new_encap, mark_t mark) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_sa *sa; + pfkey_msg_t response; + size_t len; + + /* we can't update the SA if any of the ip addresses have changed. + * that's because we can't use SADB_UPDATE and by deleting and readding the + * SA the sequence numbers would get lost */ + if (!src->ip_equals(src, new_src) || + !dst->ip_equals(dst, new_dst)) + { + DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address " + "changes are not supported", ntohl(spi)); + return NOT_SUPPORTED; + } + + /* if IPComp is used, we first update the IPComp SA */ + if (cpi) + { + update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0, + src, dst, new_src, new_dst, FALSE, FALSE, mark); + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_GET; + msg->sadb_msg_satype = proto2satype(protocol); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); + sa->sadb_sa_exttype = SADB_EXT_SA; + sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); + sa->sadb_sa_spi = spi; + PFKEY_EXT_ADD(msg, sa); + + /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though + * it is not used for anything. */ + add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC); + add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)", + ntohl(spi), strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + else if (parse_pfkey_message(out, &response) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing " + "response from kernel failed", ntohl(spi)); + free(out); + return FAILED; + } + + DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H", + ntohl(spi), src, dst, new_src, new_dst); + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_UPDATE; + msg->sadb_msg_satype = proto2satype(protocol); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + +#ifdef __APPLE__ + { + struct sadb_sa_2 *sa_2; + sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg); + sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2)); + memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa)); + if (encap) + { + sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst); + sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT; + } + } +#else + PFKEY_EXT_COPY(msg, response.sa); +#endif + PFKEY_EXT_COPY(msg, response.x_sa2); + + PFKEY_EXT_COPY(msg, response.src); + PFKEY_EXT_COPY(msg, response.dst); + + PFKEY_EXT_COPY(msg, response.lft_soft); + PFKEY_EXT_COPY(msg, response.lft_hard); + + if (response.key_encr) + { + PFKEY_EXT_COPY(msg, response.key_encr); + } + + if (response.key_auth) + { + PFKEY_EXT_COPY(msg, response.key_auth); + } + +#ifdef HAVE_NATT + if (new_encap) + { + add_encap_ext(msg, new_src, new_dst); + } +#endif /*HAVE_NATT*/ + + free(out); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)", + ntohl(spi), strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + free(out); + + return SUCCESS; +} + +METHOD(kernel_ipsec_t, query_sa, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, + u_int64_t *bytes, u_int64_t *packets, time_t *time) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_sa *sa; + pfkey_msg_t response; + size_t len; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_GET; + msg->sadb_msg_satype = proto2satype(protocol); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); + sa->sadb_sa_exttype = SADB_EXT_SA; + sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); + sa->sadb_sa_spi = spi; + PFKEY_EXT_ADD(msg, sa); + + /* the Linux Kernel doesn't care for the src address, but other systems do + * (e.g. FreeBSD) + */ + add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); + add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)", + ntohl(spi), strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + else if (parse_pfkey_message(out, &response) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); + free(out); + return FAILED; + } + if (bytes) + { + *bytes = response.lft_current->sadb_lifetime_bytes; + } + if (packets) + { + /* at least on Linux and FreeBSD this contains the number of packets */ + *packets = response.lft_current->sadb_lifetime_allocations; + } + if (time) + { +#ifdef __APPLE__ + /* OS X uses the "last" time of use in usetime */ + *time = response.lft_current->sadb_lifetime_usetime; +#else /* !__APPLE__ */ + /* on Linux, sadb_lifetime_usetime is set to the "first" time of use, + * which is actually correct according to PF_KEY. We have to query + * policies for the last usetime. */ + *time = 0; +#endif /* !__APPLE__ */ + } + + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, del_sa, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_sa *sa; + size_t len; + + /* if IPComp was used, we first delete the additional IPComp SA */ + if (cpi) + { + del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark); + } + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_DELETE; + msg->sadb_msg_satype = proto2satype(protocol); + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); + sa->sadb_sa_exttype = SADB_EXT_SA; + sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); + sa->sadb_sa_spi = spi; + PFKEY_EXT_ADD(msg, sa); + + /* the Linux Kernel doesn't care for the src address, but other systems do + * (e.g. FreeBSD) + */ + add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); + add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi)); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)", + ntohl(spi), strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + + DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi)); + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, flush_sas, status_t, + private_kernel_pfkey_ipsec_t *this) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct { + u_int8_t proto; + char *name; + } protos[] = { + { SADB_SATYPE_AH, "AH" }, + { SADB_SATYPE_ESP, "ESP" }, + { SADB_X_SATYPE_IPCOMP, "IPComp" }, + }; + size_t len; + int i; + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_FLUSH; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + for (i = 0; i < countof(protos); i++) + { + DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name); + + msg->sadb_msg_satype = protos[i].proto; + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to flush %s SAD entries: %s (%d)", + protos[i].name, strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + free(out); + } + return SUCCESS; +} + +/** + * Add an explicit exclude route to a routing entry + */ +static void add_exclude_route(private_kernel_pfkey_ipsec_t *this, + route_entry_t *route, host_t *src, host_t *dst) +{ + enumerator_t *enumerator; + exclude_route_t *exclude; + host_t *gtw; + + enumerator = this->excludes->create_enumerator(this->excludes); + while (enumerator->enumerate(enumerator, &exclude)) + { + if (dst->ip_equals(dst, exclude->dst)) + { + route->exclude = exclude; + exclude->refs++; + } + } + enumerator->destroy(enumerator); + + if (!route->exclude) + { + DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src); + gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL); + if (gtw) + { + char *if_name = NULL; + + if (charon->kernel->get_interface(charon->kernel, src, &if_name) && + charon->kernel->add_route(charon->kernel, + dst->get_address(dst), + dst->get_family(dst) == AF_INET ? 32 : 128, + gtw, src, if_name) == SUCCESS) + { + INIT(exclude, + .dst = dst->clone(dst), + .src = src->clone(src), + .gtw = gtw->clone(gtw), + .refs = 1, + ); + route->exclude = exclude; + this->excludes->insert_last(this->excludes, exclude); + } + else + { + DBG1(DBG_KNL, "installing exclude route for %H failed", dst); + } + gtw->destroy(gtw); + free(if_name); + } + else + { + DBG1(DBG_KNL, "gateway lookup for for %H failed", dst); + } + } +} + +/** + * Remove an exclude route attached to a routing entry + */ +static void remove_exclude_route(private_kernel_pfkey_ipsec_t *this, + route_entry_t *route) +{ + if (route->exclude) + { + enumerator_t *enumerator; + exclude_route_t *exclude; + bool removed = FALSE; + host_t *dst; + + enumerator = this->excludes->create_enumerator(this->excludes); + while (enumerator->enumerate(enumerator, &exclude)) + { + if (route->exclude == exclude) + { + if (--exclude->refs == 0) + { + this->excludes->remove_at(this->excludes, enumerator); + removed = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + + if (removed) + { + char *if_name = NULL; + + dst = route->exclude->dst; + DBG2(DBG_KNL, "uninstalling exclude route for %H src %H", + dst, route->exclude->src); + if (charon->kernel->get_interface( + charon->kernel, + route->exclude->src, &if_name) && + charon->kernel->del_route(charon->kernel, + dst->get_address(dst), + dst->get_family(dst) == AF_INET ? 32 : 128, + route->exclude->gtw, route->exclude->src, + if_name) != SUCCESS) + { + DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst); + } + exclude_route_destroy(route->exclude); + free(if_name); + } + route->exclude = NULL; + } +} + +/** + * Try to install a route to the given inbound policy + */ +static bool install_route(private_kernel_pfkey_ipsec_t *this, + policy_entry_t *policy, policy_sa_in_t *in) +{ + route_entry_t *route, *old; + host_t *host, *src, *dst; + bool is_virtual; + + if (charon->kernel->get_address_by_ts(charon->kernel, in->dst_ts, &host, + &is_virtual) != SUCCESS) + { + return FALSE; + } + + /* switch src/dst, as we handle an IN policy */ + src = in->generic.sa->dst; + dst = in->generic.sa->src; + + INIT(route, + .prefixlen = policy->src.mask, + .src_ip = host, + .dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)), + ); + + if (!dst->is_anyaddr(dst)) + { + route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1, + src); + + /* if the IP is virtual, we install the route over the interface it has + * been installed on. Otherwise we use the interface we use for IKE, as + * this is required for example on Linux. */ + if (is_virtual) + { + src = route->src_ip; + } + } + else + { /* for shunt policies */ + route->gateway = charon->kernel->get_nexthop(charon->kernel, + policy->src.net, policy->src.mask, + route->src_ip); + + /* we don't have a source address, use the address we found */ + src = route->src_ip; + } + + /* get interface for route, using source address */ + if (!charon->kernel->get_interface(charon->kernel, src, &route->if_name)) + { + route_entry_destroy(route); + return FALSE; + } + + if (policy->route) + { + old = policy->route; + + if (route_entry_equals(old, route)) + { /* such a route already exists */ + route_entry_destroy(route); + return TRUE; + } + /* uninstall previously installed route */ + if (charon->kernel->del_route(charon->kernel, old->dst_net, + old->prefixlen, old->gateway, + old->src_ip, old->if_name) != SUCCESS) + { + DBG1(DBG_KNL, "error uninstalling route installed with policy " + "%R === %R %N", in->src_ts, in->dst_ts, + policy_dir_names, policy->direction); + } + route_entry_destroy(old); + policy->route = NULL; + } + + /* if remote traffic selector covers the IKE peer, add an exclude route */ + if (charon->kernel->get_features(charon->kernel) & KERNEL_REQUIRE_EXCLUDE_ROUTE) + { + if (in->src_ts->is_host(in->src_ts, dst)) + { + DBG1(DBG_KNL, "can't install route for %R === %R %N, conflicts " + "with IKE traffic", in->src_ts, in->dst_ts, policy_dir_names, + policy->direction); + route_entry_destroy(route); + return FALSE; + } + if (in->src_ts->includes(in->src_ts, dst)) + { + add_exclude_route(this, route, in->generic.sa->dst, dst); + } + } + + DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", + in->src_ts, route->gateway, route->src_ip, route->if_name); + + switch (charon->kernel->add_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name)) + { + case ALREADY_DONE: + /* route exists, do not uninstall */ + remove_exclude_route(this, route); + route_entry_destroy(route); + return TRUE; + case SUCCESS: + /* cache the installed route */ + policy->route = route; + return TRUE; + default: + DBG1(DBG_KNL, "installing route failed: %R via %H src %H dev %s", + in->src_ts, route->gateway, route->src_ip, route->if_name); + remove_exclude_route(this, route); + route_entry_destroy(route); + return FALSE; + } +} + +/** + * Add or update a policy in the kernel. + * + * Note: The mutex has to be locked when entering this function. + */ +static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this, + policy_entry_t *policy, policy_sa_t *mapping, bool update) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_x_policy *pol; + struct sadb_x_ipsecrequest *req; + ipsec_sa_t *ipsec = mapping->sa; + pfkey_msg_t response; + size_t len; + ipsec_mode_t proto_mode; + status_t status; + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = update ? SADB_X_SPDUPDATE : SADB_X_SPDADD; + msg->sadb_msg_satype = 0; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); + pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; + pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); + pol->sadb_x_policy_id = 0; + pol->sadb_x_policy_dir = dir2kernel(policy->direction); + pol->sadb_x_policy_type = type2kernel(mapping->type); +#ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY + pol->sadb_x_policy_priority = mapping->priority; +#endif + + /* one or more sadb_x_ipsecrequest extensions are added to the + * sadb_x_policy extension */ + proto_mode = ipsec->cfg.mode; + + req = (struct sadb_x_ipsecrequest*)(pol + 1); + + if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE) + { + req->sadb_x_ipsecrequest_proto = IPPROTO_COMP; + + /* !!! the length here MUST be in octets instead of 64 bit words */ + req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest); + req->sadb_x_ipsecrequest_mode = mode2kernel(ipsec->cfg.mode); + req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid; + req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ? + IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE; + if (ipsec->cfg.mode == MODE_TUNNEL) + { + len = hostcpy(req + 1, ipsec->src, FALSE); + req->sadb_x_ipsecrequest_len += len; + len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE); + req->sadb_x_ipsecrequest_len += len; + /* use transport mode for other SAs */ + proto_mode = MODE_TRANSPORT; + } + + pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len); + req = (struct sadb_x_ipsecrequest*)((char*)(req) + + req->sadb_x_ipsecrequest_len); + } + + req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP + : IPPROTO_AH; + /* !!! the length here MUST be in octets instead of 64 bit words */ + req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest); + req->sadb_x_ipsecrequest_mode = mode2kernel(proto_mode); + req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid; + req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; + if (proto_mode == MODE_TUNNEL) + { + len = hostcpy(req + 1, ipsec->src, FALSE); + req->sadb_x_ipsecrequest_len += len; + len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE); + req->sadb_x_ipsecrequest_len += len; + } + + pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len); + PFKEY_EXT_ADD(msg, pol); + + add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, + policy->src.mask, TRUE); + add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, + policy->dst.mask, TRUE); + +#ifdef __FreeBSD__ + { /* on FreeBSD a lifetime has to be defined to be able to later query + * the current use time. */ + struct sadb_lifetime *lft; + lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); + lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; + lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); + lft->sadb_lifetime_addtime = LONG_MAX; + PFKEY_EXT_ADD(msg, lft); + } +#endif + + this->mutex->unlock(this->mutex); + + status = pfkey_send(this, msg, &out, &len); + if (status == SUCCESS && !update && out->sadb_msg_errno == EEXIST) + { + DBG1(DBG_KNL, "policy already exists, try to update it"); + free(out); + msg->sadb_msg_type = SADB_X_SPDUPDATE; + status = pfkey_send(this, msg, &out, &len); + } + if (status != SUCCESS) + { + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to %s policy: %s (%d)", + update ? "update" : "add", strerror(out->sadb_msg_errno), + out->sadb_msg_errno); + free(out); + return FAILED; + } + else if (parse_pfkey_message(out, &response) != SUCCESS) + { + DBG1(DBG_KNL, "unable to %s policy: parsing response from kernel " + "failed", update ? "update" : "add"); + free(out); + return FAILED; + } + + /* we try to find the policy again and update the kernel index */ + this->mutex->lock(this->mutex); + if (this->policies->find_first(this->policies, NULL, + (void**)&policy) != SUCCESS) + { + DBG2(DBG_KNL, "unable to update index, the policy is already gone, " + "ignoring"); + this->mutex->unlock(this->mutex); + free(out); + return SUCCESS; + } + policy->index = response.x_policy->sadb_x_policy_id; + free(out); + + /* install a route, if: + * - this is an inbound policy (to just get one for each child) + * - we are in tunnel mode or install a bypass policy + * - routing is not disabled via strongswan.conf + */ + if (policy->direction == POLICY_IN && this->install_routes && + (mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT)) + { + install_route(this, policy, (policy_sa_in_t*)mapping); + } + this->mutex->unlock(this->mutex); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, add_policy, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) +{ + policy_entry_t *policy, *found = NULL; + policy_sa_t *assigned_sa, *current_sa; + enumerator_t *enumerator; + bool update = TRUE; + + if (dir2kernel(direction) == IPSEC_DIR_INVALID) + { /* FWD policies are not supported on all platforms */ + return SUCCESS; + } + + /* create a policy */ + policy = create_policy_entry(src_ts, dst_ts, direction); + + /* find a matching policy */ + this->mutex->lock(this->mutex); + if (this->policies->find_first(this->policies, + (linked_list_match_t)policy_entry_equals, + (void**)&found, policy) == SUCCESS) + { /* use existing policy */ + DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " + "refcount", src_ts, dst_ts, policy_dir_names, direction); + policy_entry_destroy(policy, this); + policy = found; + } + else + { /* use the new one, if we have no such policy */ + this->policies->insert_first(this->policies, policy); + policy->used_by = linked_list_create(); + } + + /* cache the assigned IPsec SA */ + assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts, + dst_ts, sa); + assigned_sa->priority = get_priority(policy, priority); + + /* insert the SA according to its priority */ + enumerator = policy->used_by->create_enumerator(policy->used_by); + while (enumerator->enumerate(enumerator, (void**)¤t_sa)) + { + if (current_sa->priority >= assigned_sa->priority) + { + break; + } + update = FALSE; + } + policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa); + enumerator->destroy(enumerator); + + if (!update) + { /* we don't update the policy if the priority is lower than that of the + * currently installed one */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + + DBG2(DBG_KNL, "%s policy %R === %R %N", + found ? "updating" : "adding", src_ts, dst_ts, + policy_dir_names, direction); + + if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS) + { + DBG1(DBG_KNL, "unable to %s policy %R === %R %N", + found ? "update" : "add", src_ts, dst_ts, + policy_dir_names, direction); + return FAILED; + } + return SUCCESS; +} + +METHOD(kernel_ipsec_t, query_policy, status_t, + private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + time_t *use_time) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_x_policy *pol; + policy_entry_t *policy, *found = NULL; + pfkey_msg_t response; + size_t len; + + if (dir2kernel(direction) == IPSEC_DIR_INVALID) + { /* FWD policies are not supported on all platforms */ + return NOT_FOUND; + } + + DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + + /* create a policy */ + policy = create_policy_entry(src_ts, dst_ts, direction); + + /* find a matching policy */ + this->mutex->lock(this->mutex); + if (this->policies->find_first(this->policies, + (linked_list_match_t)policy_entry_equals, + (void**)&found, policy) != SUCCESS) + { + DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts, + dst_ts, policy_dir_names, direction); + policy_entry_destroy(policy, this); + this->mutex->unlock(this->mutex); + return NOT_FOUND; + } + policy_entry_destroy(policy, this); + policy = found; + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_X_SPDGET; + msg->sadb_msg_satype = 0; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); + pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; + pol->sadb_x_policy_id = policy->index; + pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); + pol->sadb_x_policy_dir = dir2kernel(direction); + pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; + PFKEY_EXT_ADD(msg, pol); + + add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, + policy->src.mask, TRUE); + add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, + policy->dst.mask, TRUE); + + this->mutex->unlock(this->mutex); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts, + dst_ts, policy_dir_names, direction, + strerror(out->sadb_msg_errno), out->sadb_msg_errno); + free(out); + return FAILED; + } + else if (parse_pfkey_message(out, &response) != SUCCESS) + { + DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response " + "from kernel failed", src_ts, dst_ts, policy_dir_names, + direction); + free(out); + return FAILED; + } + else if (response.lft_current == NULL) + { + DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no " + "use time", src_ts, dst_ts, policy_dir_names, direction); + free(out); + return FAILED; + } + + /* we need the monotonic time, but the kernel returns system time. */ + if (response.lft_current->sadb_lifetime_usetime) + { + *use_time = time_monotonic(NULL) - + (time(NULL) - response.lft_current->sadb_lifetime_usetime); + } + else + { + *use_time = 0; + } + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, del_policy, status_t, + private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t prio) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + struct sadb_x_policy *pol; + policy_entry_t *policy, *found = NULL; + policy_sa_t *mapping, *to_remove = NULL; + enumerator_t *enumerator; + bool first = TRUE, is_installed = TRUE; + u_int32_t priority; + size_t len; + ipsec_sa_t assigned_sa = { + .src = src, + .dst = dst, + .cfg = *sa, + }; + + if (dir2kernel(direction) == IPSEC_DIR_INVALID) + { /* FWD policies are not supported on all platforms */ + return SUCCESS; + } + + DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + + /* create a policy */ + policy = create_policy_entry(src_ts, dst_ts, direction); + + /* find a matching policy */ + this->mutex->lock(this->mutex); + if (this->policies->find_first(this->policies, + (linked_list_match_t)policy_entry_equals, + (void**)&found, policy) != SUCCESS) + { + DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts, + dst_ts, policy_dir_names, direction); + policy_entry_destroy(policy, this); + this->mutex->unlock(this->mutex); + return NOT_FOUND; + } + policy_entry_destroy(policy, this); + policy = found; + + /* remove mapping to SA by reqid and priority, if multiple match, which + * could happen when rekeying due to an address change, remove the oldest */ + priority = get_priority(policy, prio); + enumerator = policy->used_by->create_enumerator(policy->used_by); + while (enumerator->enumerate(enumerator, (void**)&mapping)) + { + if (priority == mapping->priority && + ipsec_sa_equals(mapping->sa, &assigned_sa)) + { + to_remove = mapping; + is_installed = first; + } + else if (priority < mapping->priority) + { + break; + } + first = FALSE; + } + enumerator->destroy(enumerator); + if (!to_remove) + { /* sanity check */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + policy->used_by->remove(policy->used_by, to_remove, NULL); + mapping = to_remove; + + if (policy->used_by->get_count(policy->used_by) > 0) + { /* policy is used by more SAs, keep in kernel */ + DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed"); + policy_sa_destroy(mapping, &direction, this); + + if (!is_installed) + { /* no need to update as the policy was not installed for this SA */ + this->mutex->unlock(this->mutex); + return SUCCESS; + } + + DBG2(DBG_KNL, "updating policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + policy->used_by->get_first(policy->used_by, (void**)&mapping); + if (add_policy_internal(this, policy, mapping, TRUE) != SUCCESS) + { + DBG1(DBG_KNL, "unable to update policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + return FAILED; + } + return SUCCESS; + } + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_X_SPDDELETE; + msg->sadb_msg_satype = 0; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); + pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; + pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); + pol->sadb_x_policy_dir = dir2kernel(direction); + pol->sadb_x_policy_type = type2kernel(mapping->type); + PFKEY_EXT_ADD(msg, pol); + + add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, + policy->src.mask, TRUE); + add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, + policy->dst.mask, TRUE); + + if (policy->route) + { + route_entry_t *route = policy->route; + if (charon->kernel->del_route(charon->kernel, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name) != SUCCESS) + { + DBG1(DBG_KNL, "error uninstalling route installed with " + "policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + } + remove_exclude_route(this, route); + } + + this->policies->remove(this->policies, found, NULL); + policy_sa_destroy(mapping, &direction, this); + policy_entry_destroy(policy, this); + this->mutex->unlock(this->mutex); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts, + dst_ts, policy_dir_names, direction, + strerror(out->sadb_msg_errno), out->sadb_msg_errno); + free(out); + return FAILED; + } + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, flush_policies, status_t, + private_kernel_pfkey_ipsec_t *this) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + size_t len; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "flushing all policies from SPD"); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_X_SPDFLUSH; + msg->sadb_msg_satype = SADB_SATYPE_UNSPEC; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + if (pfkey_send(this, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to flush SPD entries"); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to flush SPD entries: %s (%d)", + strerror(out->sadb_msg_errno), out->sadb_msg_errno); + free(out); + return FAILED; + } + free(out); + return SUCCESS; +} + +/** + * Register a socket for ACQUIRE/EXPIRE messages + */ +static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this, + u_int8_t satype) +{ + unsigned char request[PFKEY_BUFFER_SIZE]; + struct sadb_msg *msg, *out; + size_t len; + + memset(&request, 0, sizeof(request)); + + msg = (struct sadb_msg*)request; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = SADB_REGISTER; + msg->sadb_msg_satype = satype; + msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); + + if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS) + { + DBG1(DBG_KNL, "unable to register PF_KEY socket"); + return FAILED; + } + else if (out->sadb_msg_errno) + { + DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)", + strerror(out->sadb_msg_errno), out->sadb_msg_errno); + free(out); + return FAILED; + } + free(out); + return SUCCESS; +} + +METHOD(kernel_ipsec_t, bypass_socket, bool, + private_kernel_pfkey_ipsec_t *this, int fd, int family) +{ + struct sadb_x_policy policy; + u_int sol, ipsec_policy; + + switch (family) + { + case AF_INET: + { + sol = SOL_IP; + ipsec_policy = IP_IPSEC_POLICY; + break; + } + case AF_INET6: + { + sol = SOL_IPV6; + ipsec_policy = IPV6_IPSEC_POLICY; + break; + } + default: + return FALSE; + } + + memset(&policy, 0, sizeof(policy)); + policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t); + policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; + policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS; + + policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + return TRUE; +} + +METHOD(kernel_ipsec_t, enable_udp_decap, bool, + private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port) +{ +#ifndef __APPLE__ + int type = UDP_ENCAP_ESPINUDP; + + if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + { + DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno)); + return FALSE; + } +#else /* __APPLE__ */ + int intport = port; + + if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &intport, + sizeof(intport)) != 0) + { + DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s", + port, strerror(errno)); + return FALSE; + } +#endif /* __APPLE__ */ + + return TRUE; +} + +METHOD(kernel_ipsec_t, destroy, void, + private_kernel_pfkey_ipsec_t *this) +{ + if (this->socket > 0) + { + close(this->socket); + } + if (this->socket_events > 0) + { + lib->watcher->remove(lib->watcher, this->socket_events); + close(this->socket_events); + } + this->policies->invoke_function(this->policies, + (linked_list_invoke_t)policy_entry_destroy, + this); + this->policies->destroy(this->policies); + this->excludes->destroy(this->excludes); + this->sas->destroy(this->sas); + this->mutex->destroy(this->mutex); + this->mutex_pfkey->destroy(this->mutex_pfkey); + free(this); +} + +/* + * Described in header. + */ +kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create() +{ + private_kernel_pfkey_ipsec_t *this; + bool register_for_events = TRUE; + int rcv_buffer; + + INIT(this, + .public = { + .interface = { + .get_spi = _get_spi, + .get_cpi = _get_cpi, + .add_sa = _add_sa, + .update_sa = _update_sa, + .query_sa = _query_sa, + .del_sa = _del_sa, + .flush_sas = _flush_sas, + .add_policy = _add_policy, + .query_policy = _query_policy, + .del_policy = _del_policy, + .flush_policies = _flush_policies, + .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, + .destroy = _destroy, + }, + }, + .policies = linked_list_create(), + .excludes = linked_list_create(), + .sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash, + (hashtable_equals_t)ipsec_sa_equals, 32), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .mutex_pfkey = mutex_create(MUTEX_TYPE_DEFAULT), + .install_routes = lib->settings->get_bool(lib->settings, + "%s.install_routes", TRUE, + lib->ns), + ); + + if (streq(lib->ns, "starter")) + { /* starter has no threads, so we do not register for kernel events */ + register_for_events = FALSE; + } + + /* create a PF_KEY socket to communicate with the kernel */ + this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + if (this->socket <= 0) + { + DBG1(DBG_KNL, "unable to create PF_KEY socket"); + destroy(this); + return NULL; + } + + if (register_for_events) + { + /* create a PF_KEY socket for ACQUIRE & EXPIRE */ + this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + if (this->socket_events <= 0) + { + DBG1(DBG_KNL, "unable to create PF_KEY event socket"); + destroy(this); + return NULL; + } + + rcv_buffer = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-pfkey.events_buffer_size", 0, lib->ns); + if (rcv_buffer > 0) + { + if (setsockopt(this->socket_events, SOL_SOCKET, SO_RCVBUF, + &rcv_buffer, sizeof(rcv_buffer)) == -1) + { + DBG1(DBG_KNL, "unable to set receive buffer size on PF_KEY " + "event socket: %s", strerror(errno)); + } + } + + /* register the event socket */ + if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS || + register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS) + { + DBG1(DBG_KNL, "unable to register PF_KEY event socket"); + destroy(this); + return NULL; + } + + lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ, + (watcher_cb_t)receive_events, this); + } + + return &this->public; +} diff --git a/src/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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..d49fe2422 --- /dev/null +++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "kernel_pfkey_plugin.h" + +#include "kernel_pfkey_ipsec.h" + +typedef struct private_kernel_pfkey_plugin_t private_kernel_pfkey_plugin_t; + +/** + * private data of kernel PF_KEY plugin + */ +struct private_kernel_pfkey_plugin_t { + /** + * implements plugin interface + */ + kernel_pfkey_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_kernel_pfkey_plugin_t *this) +{ + return "kernel-pfkey"; +} + +METHOD(plugin_t, get_features, int, + private_kernel_pfkey_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(kernel_ipsec_register, kernel_pfkey_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_kernel_pfkey_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *kernel_pfkey_plugin_create() +{ + private_kernel_pfkey_plugin_t *this; + + if (!lib->caps->check(lib->caps, CAP_NET_ADMIN)) + { /* required to open PF_KEY sockets */ + DBG1(DBG_KNL, "kernel-pfkey plugin requires CAP_NET_ADMIN capability"); + return NULL; + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h new file mode 100644 index 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..51047e38a --- /dev/null +++ b/src/libcharon/plugins/kernel_pfroute/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la +else +plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la +endif + +libstrongswan_kernel_pfroute_la_SOURCES = \ + kernel_pfroute_plugin.h kernel_pfroute_plugin.c \ + kernel_pfroute_net.h kernel_pfroute_net.c + +libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in new file mode 100644 index 000000000..77d83cbca --- /dev/null +++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in @@ -0,0 +1,782 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/kernel_pfroute +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_kernel_pfroute_la_LIBADD = +am_libstrongswan_kernel_pfroute_la_OBJECTS = kernel_pfroute_plugin.lo \ + kernel_pfroute_net.lo +libstrongswan_kernel_pfroute_la_OBJECTS = \ + $(am_libstrongswan_kernel_pfroute_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_kernel_pfroute_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_kernel_pfroute_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfroute_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfroute_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES) +DIST_SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CPPFLAGS = \ + -I${linux_headers} \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-kernel-pfroute.la: $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfroute_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_kernel_pfroute_la_LINK) $(am_libstrongswan_kernel_pfroute_la_rpath) $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@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@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pluginLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c new file mode 100644 index 000000000..4eebdfdad --- /dev/null +++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c @@ -0,0 +1,1902 @@ +/* + * Copyright (C) 2009-2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kernel_pfroute_net.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN +#error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member. +#endif + +/** properly align sockaddrs */ +#ifdef __APPLE__ +/* Apple always uses 4 bytes */ +#define SA_ALIGN 4 +#else +/* while on other platforms like FreeBSD it depends on the architecture */ +#define SA_ALIGN sizeof(long) +#endif +#define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN) + +/** delay before firing roam events (ms) */ +#define ROAM_DELAY 100 + +/** delay before reinstalling routes (ms) */ +#define ROUTE_DELAY 100 + +typedef struct addr_entry_t addr_entry_t; + +/** + * IP address in an inface_entry_t + */ +struct addr_entry_t { + + /** The ip address */ + host_t *ip; + + /** virtual IP managed by us */ + bool virtual; +}; + +/** + * destroy a addr_entry_t object + */ +static void addr_entry_destroy(addr_entry_t *this) +{ + this->ip->destroy(this->ip); + free(this); +} + +typedef struct iface_entry_t iface_entry_t; + +/** + * A network interface on this system, containing addr_entry_t's + */ +struct iface_entry_t { + + /** interface index */ + int ifindex; + + /** name of the interface */ + char ifname[IFNAMSIZ]; + + /** interface flags, as in netdevice(7) SIOCGIFFLAGS */ + u_int flags; + + /** list of addresses as host_t */ + linked_list_t *addrs; + + /** TRUE if usable by config */ + bool usable; +}; + +/** + * destroy an interface entry + */ +static void iface_entry_destroy(iface_entry_t *this) +{ + this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy); + free(this); +} + +/** + * check if an interface is up + */ +static inline bool iface_entry_up(iface_entry_t *iface) +{ + return (iface->flags & IFF_UP) == IFF_UP; +} + +/** + * check if an interface is up and usable + */ +static inline bool iface_entry_up_and_usable(iface_entry_t *iface) +{ + return iface->usable && iface_entry_up(iface); +} + +typedef struct addr_map_entry_t addr_map_entry_t; + +/** + * Entry that maps an IP address to an interface entry + */ +struct addr_map_entry_t { + /** The IP address */ + host_t *ip; + + /** The address entry for this IP address */ + addr_entry_t *addr; + + /** The interface this address is installed on */ + iface_entry_t *iface; +}; + +/** + * Hash a addr_map_entry_t object, all entries with the same IP address + * are stored in the same bucket + */ +static u_int addr_map_entry_hash(addr_map_entry_t *this) +{ + return chunk_hash(this->ip->get_address(this->ip)); +} + +/** + * Compare two addr_map_entry_t objects, two entries are equal if they are + * installed on the same interface + */ +static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return a->iface->ifindex == b->iface->ifindex && + a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed on + * an up and usable interface + */ +static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a, + addr_map_entry_t *b) +{ + return !b->addr->virtual && iface_entry_up_and_usable(b->iface) && + a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed as virtual + * IP address + */ +static bool addr_map_entry_match_virtual(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return b->addr->virtual && a->ip->ip_equals(a->ip, b->ip); +} + +/** + * Used with get_match this finds an address entry if it is installed on + * any active local interface + */ +static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b) +{ + return !b->addr->virtual && iface_entry_up(b->iface) && + a->ip->ip_equals(a->ip, b->ip); +} + +typedef struct route_entry_t route_entry_t; + +/** + * Installed routing entry + */ +struct route_entry_t { + /** Name of the interface the route is bound to */ + char *if_name; + + /** Gateway for this route */ + host_t *gateway; + + /** Destination net */ + chunk_t dst_net; + + /** Destination net prefixlen */ + u_int8_t prefixlen; +}; + +/** + * Clone a route_entry_t object. + */ +static route_entry_t *route_entry_clone(route_entry_t *this) +{ + route_entry_t *route; + + INIT(route, + .if_name = strdup(this->if_name), + .gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL, + .dst_net = chunk_clone(this->dst_net), + .prefixlen = this->prefixlen, + ); + return route; +} + +/** + * Destroy a route_entry_t object + */ +static void route_entry_destroy(route_entry_t *this) +{ + free(this->if_name); + DESTROY_IF(this->gateway); + chunk_free(&this->dst_net); + free(this); +} + +/** + * Hash a route_entry_t object + */ +static u_int route_entry_hash(route_entry_t *this) +{ + return chunk_hash_inc(chunk_from_thing(this->prefixlen), + chunk_hash(this->dst_net)); +} + +/** + * Compare two route_entry_t objects + */ +static bool route_entry_equals(route_entry_t *a, route_entry_t *b) +{ + if (a->if_name && b->if_name && streq(a->if_name, b->if_name) && + chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen) + { + return (!a->gateway && !b->gateway) || (a->gateway && b->gateway && + a->gateway->ip_equals(a->gateway, b->gateway)); + } + return FALSE; +} + +typedef struct net_change_t net_change_t; + +/** + * Queued network changes + */ +struct net_change_t { + /** Name of the interface that got activated (or an IP appeared on) */ + char *if_name; +}; + +/** + * Destroy a net_change_t object + */ +static void net_change_destroy(net_change_t *this) +{ + free(this->if_name); + free(this); +} + +/** + * Hash a net_change_t object + */ +static u_int net_change_hash(net_change_t *this) +{ + return chunk_hash(chunk_create(this->if_name, strlen(this->if_name))); +} + +/** + * Compare two net_change_t objects + */ +static bool net_change_equals(net_change_t *a, net_change_t *b) +{ + return streq(a->if_name, b->if_name); +} + +typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t; + +/** + * Private variables and functions of kernel_pfroute class. + */ +struct private_kernel_pfroute_net_t +{ + /** + * Public part of the kernel_pfroute_t object. + */ + kernel_pfroute_net_t public; + + /** + * lock to access lists and maps + */ + rwlock_t *lock; + + /** + * Cached list of interfaces and their addresses (iface_entry_t) + */ + linked_list_t *ifaces; + + /** + * Map for IP addresses to iface_entry_t objects (addr_map_entry_t) + */ + hashtable_t *addrs; + + /** + * List of tun devices we installed for virtual IPs + */ + linked_list_t *tuns; + + /** + * mutex to communicate exclusively with PF_KEY + */ + mutex_t *mutex; + + /** + * condvar to signal if PF_KEY query got a response + */ + condvar_t *condvar; + + /** + * installed routes + */ + hashtable_t *routes; + + /** + * mutex for routes + */ + mutex_t *routes_lock; + + /** + * interface changes which may trigger route reinstallation + */ + hashtable_t *net_changes; + + /** + * mutex for route reinstallation triggers + */ + mutex_t *net_changes_lock; + + /** + * time of last route reinstallation + */ + timeval_t last_route_reinstall; + + /** + * pid to send PF_ROUTE messages with + */ + pid_t pid; + + /** + * PF_ROUTE socket to communicate with the kernel + */ + int socket; + + /** + * sequence number for messages sent to the kernel + */ + int seq; + + /** + * Sequence number a query is waiting for + */ + int waiting_seq; + + /** + * Allocated reply message from kernel + */ + struct rt_msghdr *reply; + + /** + * earliest time of the next roam event + */ + timeval_t next_roam; + + /** + * roam event due to address change + */ + bool roam_address; + + /** + * lock to check and update roam event time + */ + spinlock_t *roam_lock; + + /** + * Time in ms to wait for IP addresses to appear/disappear + */ + int vip_wait; + + /** + * whether to actually install virtual IPs + */ + bool install_virtual_ip; +}; + + +/** + * Forward declaration + */ +static status_t manage_route(private_kernel_pfroute_net_t *this, int op, + chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, char *if_name); + +/** + * Clear the queued network changes. + */ +static void net_changes_clear(private_kernel_pfroute_net_t *this) +{ + enumerator_t *enumerator; + net_change_t *change; + + enumerator = this->net_changes->create_enumerator(this->net_changes); + while (enumerator->enumerate(enumerator, NULL, (void**)&change)) + { + this->net_changes->remove_at(this->net_changes, enumerator); + net_change_destroy(change); + } + enumerator->destroy(enumerator); +} + +/** + * Act upon queued network changes. + */ +static job_requeue_t reinstall_routes(private_kernel_pfroute_net_t *this) +{ + enumerator_t *enumerator; + route_entry_t *route; + + this->net_changes_lock->lock(this->net_changes_lock); + this->routes_lock->lock(this->routes_lock); + + enumerator = this->routes->create_enumerator(this->routes); + while (enumerator->enumerate(enumerator, NULL, (void**)&route)) + { + net_change_t *change, lookup = { + .if_name = route->if_name, + }; + /* check if a change for the outgoing interface is queued */ + change = this->net_changes->get(this->net_changes, &lookup); + if (change) + { + manage_route(this, RTM_ADD, route->dst_net, route->prefixlen, + route->gateway, route->if_name); + } + } + enumerator->destroy(enumerator); + this->routes_lock->unlock(this->routes_lock); + + net_changes_clear(this); + this->net_changes_lock->unlock(this->net_changes_lock); + return JOB_REQUEUE_NONE; +} + +/** + * Queue route reinstallation caused by network changes for a given interface. + * + * The route reinstallation is delayed for a while and only done once for + * several calls during this delay, in order to avoid doing it too often. + * The interface name is freed. + */ +static void queue_route_reinstall(private_kernel_pfroute_net_t *this, + char *if_name) +{ + net_change_t *update, *found; + timeval_t now; + job_t *job; + + INIT(update, + .if_name = if_name + ); + + this->net_changes_lock->lock(this->net_changes_lock); + found = this->net_changes->put(this->net_changes, update, update); + if (found) + { + net_change_destroy(found); + } + time_monotonic(&now); + if (timercmp(&now, &this->last_route_reinstall, >)) + { + timeval_add_ms(&now, ROUTE_DELAY); + this->last_route_reinstall = now; + + job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes, + this, NULL, NULL); + lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY); + } + this->net_changes_lock->unlock(this->net_changes_lock); +} + +/** + * Add an address map entry + */ +static void addr_map_entry_add(private_kernel_pfroute_net_t *this, + addr_entry_t *addr, iface_entry_t *iface) +{ + addr_map_entry_t *entry; + + INIT(entry, + .ip = addr->ip, + .addr = addr, + .iface = iface, + ); + entry = this->addrs->put(this->addrs, entry, entry); + free(entry); +} + +/** + * Remove an address map entry (the argument order is a bit strange because + * it is also used with linked_list_t.invoke_function) + */ +static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface, + private_kernel_pfroute_net_t *this) +{ + addr_map_entry_t *entry, lookup = { + .ip = addr->ip, + .addr = addr, + .iface = iface, + }; + + entry = this->addrs->remove(this->addrs, &lookup); + free(entry); +} + +/** + * callback function that raises the delayed roam event + */ +static job_requeue_t roam_event(private_kernel_pfroute_net_t *this) +{ + bool address; + + this->roam_lock->lock(this->roam_lock); + address = this->roam_address; + this->roam_address = FALSE; + this->roam_lock->unlock(this->roam_lock); + charon->kernel->roam(charon->kernel, address); + return JOB_REQUEUE_NONE; +} + +/** + * fire a roaming event. we delay it for a bit and fire only one event + * for multiple calls. otherwise we would create too many events. + */ +static void fire_roam_event(private_kernel_pfroute_net_t *this, bool address) +{ + timeval_t now; + job_t *job; + + time_monotonic(&now); + this->roam_lock->lock(this->roam_lock); + this->roam_address |= address; + if (!timercmp(&now, &this->next_roam, >)) + { + this->roam_lock->unlock(this->roam_lock); + return; + } + timeval_add_ms(&now, ROAM_DELAY); + this->next_roam = now; + this->roam_lock->unlock(this->roam_lock); + + job = (job_t*)callback_job_create((callback_job_cb_t)roam_event, + this, NULL, NULL); + lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY); +} + +/** + * Data for enumerator over rtmsg sockaddrs + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** copy of attribute bitfield */ + int types; + /** bytes remaining in buffer */ + int remaining; + /** next sockaddr to enumerate */ + struct sockaddr *addr; +} rt_enumerator_t; + +METHOD(enumerator_t, rt_enumerate, bool, + rt_enumerator_t *this, int *xtype, struct sockaddr **addr) +{ + int i, type; + + if (this->remaining < sizeof(this->addr->sa_len) || + this->remaining < this->addr->sa_len) + { + return FALSE; + } + for (i = 0; i < RTAX_MAX; i++) + { + type = (1 << i); + if (this->types & type) + { + this->types &= ~type; + *addr = this->addr; + *xtype = i; + this->remaining -= SA_LEN(this->addr->sa_len); + this->addr = (struct sockaddr*)((char*)this->addr + + SA_LEN(this->addr->sa_len)); + return TRUE; + } + } + return FALSE; +} + +/** + * Create an enumerator over sockaddrs in rt/if messages + */ +static enumerator_t *create_rt_enumerator(int types, int remaining, + struct sockaddr *addr) +{ + rt_enumerator_t *this; + + INIT(this, + .public = { + .enumerate = (void*)_rt_enumerate, + .destroy = (void*)free, + }, + .types = types, + .remaining = remaining, + .addr = addr, + ); + return &this->public; +} + +/** + * Create a safe enumerator over sockaddrs in rt_msghdr + */ +static enumerator_t *create_rtmsg_enumerator(struct rt_msghdr *hdr) +{ + return create_rt_enumerator(hdr->rtm_addrs, hdr->rtm_msglen - sizeof(*hdr), + (struct sockaddr *)(hdr + 1)); +} + +/** + * Create a safe enumerator over sockaddrs in ifa_msghdr + */ +static enumerator_t *create_ifamsg_enumerator(struct ifa_msghdr *hdr) +{ + return create_rt_enumerator(hdr->ifam_addrs, hdr->ifam_msglen - sizeof(*hdr), + (struct sockaddr *)(hdr + 1)); +} + +/** + * Process an RTM_*ADDR message from the kernel + */ +static void process_addr(private_kernel_pfroute_net_t *this, + struct ifa_msghdr *ifa) +{ + struct sockaddr *sockaddr; + host_t *host = NULL; + enumerator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; + bool found = FALSE, changed = FALSE, roam = FALSE; + enumerator_t *enumerator; + char *ifname = NULL; + int type; + + enumerator = create_ifamsg_enumerator(ifa); + while (enumerator->enumerate(enumerator, &type, &sockaddr)) + { + if (type == RTAX_IFA) + { + host = host_create_from_sockaddr(sockaddr); + break; + } + } + enumerator->destroy(enumerator); + + if (!host || host->is_anyaddr(host)) + { + DESTROY_IF(host); + return; + } + + this->lock->write_lock(this->lock); + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (iface->ifindex == ifa->ifam_index) + { + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, &addr)) + { + if (host->ip_equals(host, addr->ip)) + { + found = TRUE; + if (ifa->ifam_type == RTM_DELADDR) + { + iface->addrs->remove_at(iface->addrs, addrs); + if (!addr->virtual && iface->usable) + { + changed = TRUE; + DBG1(DBG_KNL, "%H disappeared from %s", + host, iface->ifname); + } + addr_map_entry_remove(addr, iface, this); + addr_entry_destroy(addr); + } + } + } + addrs->destroy(addrs); + + if (!found && ifa->ifam_type == RTM_NEWADDR) + { + INIT(addr, + .ip = host->clone(host), + ); + changed = TRUE; + ifname = strdup(iface->ifname); + iface->addrs->insert_last(iface->addrs, addr); + addr_map_entry_add(this, addr, iface); + if (iface->usable) + { + DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); + } + } + + if (changed && iface_entry_up_and_usable(iface)) + { + roam = TRUE; + } + break; + } + } + ifaces->destroy(ifaces); + this->lock->unlock(this->lock); + host->destroy(host); + + if (roam && ifname) + { + queue_route_reinstall(this, ifname); + } + else + { + free(ifname); + } + + if (roam) + { + fire_roam_event(this, TRUE); + } +} + +/** + * Re-initialize address list of an interface if it changes state + */ +static void repopulate_iface(private_kernel_pfroute_net_t *this, + iface_entry_t *iface) +{ + struct ifaddrs *ifap, *ifa; + addr_entry_t *addr; + + while (iface->addrs->remove_last(iface->addrs, (void**)&addr) == SUCCESS) + { + addr_map_entry_remove(addr, iface, this); + addr_entry_destroy(addr); + } + + if (getifaddrs(&ifap) == 0) + { + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr && streq(ifa->ifa_name, iface->ifname)) + { + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + case AF_INET6: + INIT(addr, + .ip = host_create_from_sockaddr(ifa->ifa_addr), + ); + iface->addrs->insert_last(iface->addrs, addr); + addr_map_entry_add(this, addr, iface); + break; + default: + break; + } + } + } + freeifaddrs(ifap); + } +} + +/** + * Process an RTM_IFINFO message from the kernel + */ +static void process_link(private_kernel_pfroute_net_t *this, + struct if_msghdr *msg) +{ + enumerator_t *enumerator; + iface_entry_t *iface; + bool roam = FALSE, found = FALSE, update_routes = FALSE; + + this->lock->write_lock(this->lock); + enumerator = this->ifaces->create_enumerator(this->ifaces); + while (enumerator->enumerate(enumerator, &iface)) + { + if (iface->ifindex == msg->ifm_index) + { + if (iface->usable) + { + if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP)) + { + roam = update_routes = TRUE; + DBG1(DBG_KNL, "interface %s activated", iface->ifname); + } + else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP)) + { + roam = TRUE; + DBG1(DBG_KNL, "interface %s deactivated", iface->ifname); + } + } +#ifdef __APPLE__ + /* There seems to be a race condition on 10.10, where we get + * the RTM_IFINFO, but getifaddrs() does not return the virtual + * IP installed on a tun device, but we also don't get a + * RTM_NEWADDR. We therefore could miss the new address, letting + * virtual IP installation fail. Delaying getifaddrs() helps, + * but is obviously not a clean fix. */ + usleep(50000); +#endif + iface->flags = msg->ifm_flags; + repopulate_iface(this, iface); + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + INIT(iface, + .ifindex = msg->ifm_index, + .flags = msg->ifm_flags, + .addrs = linked_list_create(), + ); + if (if_indextoname(iface->ifindex, iface->ifname)) + { + DBG1(DBG_KNL, "interface %s appeared", iface->ifname); + iface->usable = charon->kernel->is_interface_usable(charon->kernel, + iface->ifname); + repopulate_iface(this, iface); + this->ifaces->insert_last(this->ifaces, iface); + if (iface->usable) + { + roam = update_routes = TRUE; + } + } + else + { + free(iface); + } + } + this->lock->unlock(this->lock); + + if (update_routes) + { + queue_route_reinstall(this, strdup(iface->ifname)); + } + + if (roam) + { + fire_roam_event(this, TRUE); + } +} + +#ifdef HAVE_RTM_IFANNOUNCE + +/** + * Process an RTM_IFANNOUNCE message from the kernel + */ +static void process_announce(private_kernel_pfroute_net_t *this, + struct if_announcemsghdr *msg) +{ + enumerator_t *enumerator; + iface_entry_t *iface; + + if (msg->ifan_what != IFAN_DEPARTURE) + { + /* we handle new interfaces in process_link() */ + return; + } + + this->lock->write_lock(this->lock); + enumerator = this->ifaces->create_enumerator(this->ifaces); + while (enumerator->enumerate(enumerator, &iface)) + { + if (iface->ifindex == msg->ifan_index) + { + DBG1(DBG_KNL, "interface %s disappeared", iface->ifname); + this->ifaces->remove_at(this->ifaces, enumerator); + iface_entry_destroy(iface); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +#endif /* HAVE_RTM_IFANNOUNCE */ + +/** + * Process an RTM_*ROUTE message from the kernel + */ +static void process_route(private_kernel_pfroute_net_t *this, + struct rt_msghdr *msg) +{ + +} + +/** + * Receives PF_ROUTE messages from kernel + */ +static bool receive_events(private_kernel_pfroute_net_t *this, int fd, + watcher_event_t event) +{ + struct { + union { + struct rt_msghdr rtm; + struct if_msghdr ifm; + struct ifa_msghdr ifam; +#ifdef HAVE_RTM_IFANNOUNCE + struct if_announcemsghdr ifanm; +#endif + }; + char buf[sizeof(struct sockaddr_storage) * RTAX_MAX]; + } msg; + int len, hdrlen; + + len = recv(this->socket, &msg, sizeof(msg), MSG_DONTWAIT); + if (len < 0) + { + switch (errno) + { + case EINTR: + case EAGAIN: + return TRUE; + default: + DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket"); + sleep(1); + return TRUE; + } + } + + if (len < offsetof(struct rt_msghdr, rtm_flags) || len < msg.rtm.rtm_msglen) + { + DBG1(DBG_KNL, "received invalid PF_ROUTE message"); + return TRUE; + } + if (msg.rtm.rtm_version != RTM_VERSION) + { + DBG1(DBG_KNL, "received PF_ROUTE message with unsupported version: %d", + msg.rtm.rtm_version); + return TRUE; + } + switch (msg.rtm.rtm_type) + { + case RTM_NEWADDR: + case RTM_DELADDR: + hdrlen = sizeof(msg.ifam); + break; + case RTM_IFINFO: + hdrlen = sizeof(msg.ifm); + break; +#ifdef HAVE_RTM_IFANNOUNCE + case RTM_IFANNOUNCE: + hdrlen = sizeof(msg.ifanm); + break; +#endif /* HAVE_RTM_IFANNOUNCE */ + case RTM_ADD: + case RTM_DELETE: + case RTM_GET: + hdrlen = sizeof(msg.rtm); + break; + default: + return TRUE; + } + if (msg.rtm.rtm_msglen < hdrlen) + { + DBG1(DBG_KNL, "ignoring short PF_ROUTE message"); + return TRUE; + } + switch (msg.rtm.rtm_type) + { + case RTM_NEWADDR: + case RTM_DELADDR: + process_addr(this, &msg.ifam); + break; + case RTM_IFINFO: + process_link(this, &msg.ifm); + break; +#ifdef HAVE_RTM_IFANNOUNCE + case RTM_IFANNOUNCE: + process_announce(this, &msg.ifanm); + break; +#endif /* HAVE_RTM_IFANNOUNCE */ + case RTM_ADD: + case RTM_DELETE: + process_route(this, &msg.rtm); + break; + default: + break; + } + + this->mutex->lock(this->mutex); + if (msg.rtm.rtm_pid == this->pid && msg.rtm.rtm_seq == this->waiting_seq) + { + /* seems like the message someone is waiting for, deliver */ + this->reply = realloc(this->reply, msg.rtm.rtm_msglen); + memcpy(this->reply, &msg, msg.rtm.rtm_msglen); + } + /* signal on any event, add_ip()/del_ip() might wait for it */ + this->condvar->broadcast(this->condvar); + this->mutex->unlock(this->mutex); + + return TRUE; +} + + +/** enumerator over addresses */ +typedef struct { + private_kernel_pfroute_net_t* this; + /** which addresses to enumerate */ + kernel_address_type_t which; +} address_enumerator_t; + +/** + * cleanup function for address enumerator + */ +static void address_enumerator_destroy(address_enumerator_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * filter for addresses + */ +static bool filter_addresses(address_enumerator_t *data, + addr_entry_t** in, host_t** out) +{ + host_t *ip; + if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual) + { /* skip virtual interfaces added by us */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->virtual) + { /* address is regular, but not requested */ + return FALSE; + } + ip = (*in)->ip; + if (ip->get_family(ip) == AF_INET6) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip); + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + { /* skip addresses with a unusable scope */ + return FALSE; + } + } + *out = ip; + return TRUE; +} + +/** + * enumerator constructor for interfaces + */ +static enumerator_t *create_iface_enumerator(iface_entry_t *iface, + address_enumerator_t *data) +{ + return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs), + (void*)filter_addresses, data, NULL); +} + +/** + * filter for interfaces + */ +static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, + iface_entry_t** out) +{ + if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable) + { /* skip interfaces excluded by config */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK)) + { /* ignore loopback devices */ + return FALSE; + } + if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP)) + { /* skip interfaces not up */ + return FALSE; + } + *out = *in; + return TRUE; +} + +METHOD(kernel_net_t, create_address_enumerator, enumerator_t*, + private_kernel_pfroute_net_t *this, kernel_address_type_t which) +{ + address_enumerator_t *data; + + INIT(data, + .this = this, + .which = which, + ); + + this->lock->read_lock(this->lock); + return enumerator_create_nested( + enumerator_create_filter( + this->ifaces->create_enumerator(this->ifaces), + (void*)filter_interfaces, data, NULL), + (void*)create_iface_enumerator, data, + (void*)address_enumerator_destroy); +} + +METHOD(kernel_net_t, get_features, kernel_feature_t, + private_kernel_pfroute_net_t *this) +{ + return KERNEL_REQUIRE_EXCLUDE_ROUTE; +} + +METHOD(kernel_net_t, get_interface_name, bool, + private_kernel_pfroute_net_t *this, host_t* ip, char **name) +{ + addr_map_entry_t *entry, lookup = { + .ip = ip, + }; + + if (ip->is_anyaddr(ip)) + { + return FALSE; + } + this->lock->read_lock(this->lock); + /* first try to find it on an up and usable interface */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_up_and_usable); + if (entry) + { + if (name) + { + *name = strdup(entry->iface->ifname); + DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + } + this->lock->unlock(this->lock); + return TRUE; + } + /* check if it is a virtual IP */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_virtual); + if (entry) + { + if (name) + { + *name = strdup(entry->iface->ifname); + DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name); + } + this->lock->unlock(this->lock); + return TRUE; + } + /* maybe it is installed on an ignored interface */ + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_up); + if (!entry) + { /* the address does not exist, is on a down interface */ + DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip); + } + this->lock->unlock(this->lock); + return FALSE; +} + +METHOD(kernel_net_t, add_ip, status_t, + private_kernel_pfroute_net_t *this, host_t *vip, int prefix, + char *ifname) +{ + enumerator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; + tun_device_t *tun; + bool timeout = FALSE; + + if (!this->install_virtual_ip) + { /* disabled by config */ + return SUCCESS; + } + + tun = tun_device_create(NULL); + if (!tun) + { + return FAILED; + } + if (prefix == -1) + { + prefix = vip->get_address(vip).len * 8; + } + if (!tun->up(tun) || !tun->set_address(tun, vip, prefix)) + { + tun->destroy(tun); + return FAILED; + } + + /* wait until address appears */ + this->mutex->lock(this->mutex); + while (!timeout && !get_interface_name(this, vip, NULL)) + { + timeout = this->condvar->timed_wait(this->condvar, this->mutex, + this->vip_wait); + } + this->mutex->unlock(this->mutex); + if (timeout) + { + DBG1(DBG_KNL, "virtual IP %H did not appear on %s", + vip, tun->get_name(tun)); + tun->destroy(tun); + return FAILED; + } + + this->lock->write_lock(this->lock); + this->tuns->insert_last(this->tuns, tun); + + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (streq(iface->ifname, tun->get_name(tun))) + { + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, &addr)) + { + if (addr->ip->ip_equals(addr->ip, vip)) + { + addr->virtual = TRUE; + } + } + addrs->destroy(addrs); + /* during IKEv1 reauthentication, children get moved from + * old the new SA before the virtual IP is available. This + * kills the route for our virtual IP, reinstall. */ + queue_route_reinstall(this, strdup(iface->ifname)); + break; + } + } + ifaces->destroy(ifaces); + /* lets do this while holding the lock, thus preventing another thread + * from deleting the TUN device concurrently, hopefully listeners are quick + * and cause no deadlocks */ + charon->kernel->tun(charon->kernel, tun, TRUE); + this->lock->unlock(this->lock); + + return SUCCESS; +} + +METHOD(kernel_net_t, del_ip, status_t, + private_kernel_pfroute_net_t *this, host_t *vip, int prefix, + bool wait) +{ + enumerator_t *enumerator; + tun_device_t *tun; + host_t *addr; + bool timeout = FALSE, found = FALSE; + + if (!this->install_virtual_ip) + { /* disabled by config */ + return SUCCESS; + } + + this->lock->write_lock(this->lock); + enumerator = this->tuns->create_enumerator(this->tuns); + while (enumerator->enumerate(enumerator, &tun)) + { + addr = tun->get_address(tun, NULL); + if (addr && addr->ip_equals(addr, vip)) + { + this->tuns->remove_at(this->tuns, enumerator); + charon->kernel->tun(charon->kernel, tun, FALSE); + tun->destroy(tun); + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + if (!found) + { + return NOT_FOUND; + } + /* wait until address disappears */ + if (wait) + { + this->mutex->lock(this->mutex); + while (!timeout && get_interface_name(this, vip, NULL)) + { + timeout = this->condvar->timed_wait(this->condvar, this->mutex, + this->vip_wait); + } + this->mutex->unlock(this->mutex); + if (timeout) + { + DBG1(DBG_KNL, "virtual IP %H did not disappear from tun", vip); + return FAILED; + } + } + return SUCCESS; +} + +/** + * Append a sockaddr_in/in6 of given type to routing message + */ +static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr) +{ + if (addr) + { + int len; + + len = *addr->get_sockaddr_len(addr); + memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len); + hdr->rtm_msglen += SA_LEN(len); + hdr->rtm_addrs |= type; + } +} + +/** + * Append a subnet mask sockaddr using the given prefix to routing message + */ +static void add_rt_mask(struct rt_msghdr *hdr, int type, int family, int prefix) +{ + host_t *mask; + + mask = host_create_netmask(family, prefix); + if (mask) + { + add_rt_addr(hdr, type, mask); + mask->destroy(mask); + } +} + +/** + * Append an interface name sockaddr_dl to routing message + */ +static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name) +{ + struct sockaddr_dl sdl = { + .sdl_len = sizeof(struct sockaddr_dl), + .sdl_family = AF_LINK, + .sdl_nlen = strlen(name), + }; + + if (strlen(name) <= sizeof(sdl.sdl_data)) + { + memcpy(sdl.sdl_data, name, sdl.sdl_nlen); + memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len); + hdr->rtm_msglen += SA_LEN(sdl.sdl_len); + hdr->rtm_addrs |= type; + } +} + +/** + * Add or remove a route + */ +static status_t manage_route(private_kernel_pfroute_net_t *this, int op, + chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, char *if_name) +{ + struct { + struct rt_msghdr hdr; + char buf[sizeof(struct sockaddr_storage) * RTAX_MAX]; + } msg = { + .hdr = { + .rtm_version = RTM_VERSION, + .rtm_type = op, + .rtm_flags = RTF_UP | RTF_STATIC, + .rtm_pid = this->pid, + .rtm_seq = ref_get(&this->seq), + }, + }; + host_t *dst; + int type; + + if (prefixlen == 0 && dst_net.len) + { + status_t status; + chunk_t half; + + half = chunk_clonea(dst_net); + half.ptr[0] |= 0x80; + prefixlen = 1; + status = manage_route(this, op, half, prefixlen, gateway, if_name); + if (status != SUCCESS) + { + return status; + } + } + + dst = host_create_from_chunk(AF_UNSPEC, dst_net, 0); + if (!dst) + { + return FAILED; + } + + if ((dst->get_family(dst) == AF_INET && prefixlen == 32) || + (dst->get_family(dst) == AF_INET6 && prefixlen == 128)) + { + msg.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY; + } + + msg.hdr.rtm_msglen = sizeof(struct rt_msghdr); + for (type = 0; type < RTAX_MAX; type++) + { + switch (type) + { + case RTAX_DST: + add_rt_addr(&msg.hdr, RTA_DST, dst); + break; + case RTAX_NETMASK: + if (!(msg.hdr.rtm_flags & RTF_HOST)) + { + add_rt_mask(&msg.hdr, RTA_NETMASK, + dst->get_family(dst), prefixlen); + } + break; + case RTAX_IFP: + if (if_name) + { + add_rt_ifname(&msg.hdr, RTA_IFP, if_name); + } + break; + case RTAX_GATEWAY: + if (gateway) + { + add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway); + } + break; + default: + break; + } + } + dst->destroy(dst); + + if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) != msg.hdr.rtm_msglen) + { + if (errno == EEXIST) + { + return ALREADY_DONE; + } + DBG1(DBG_KNL, "%s PF_ROUTE route failed: %s", + op == RTM_ADD ? "adding" : "deleting", strerror(errno)); + return FAILED; + } + return SUCCESS; +} + +METHOD(kernel_net_t, add_route, status_t, + private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) +{ + status_t status; + route_entry_t *found, route = { + .dst_net = dst_net, + .prefixlen = prefixlen, + .gateway = gateway, + .if_name = if_name, + }; + + this->routes_lock->lock(this->routes_lock); + found = this->routes->get(this->routes, &route); + if (found) + { + this->routes_lock->unlock(this->routes_lock); + return ALREADY_DONE; + } + status = manage_route(this, RTM_ADD, dst_net, prefixlen, gateway, if_name); + if (status == SUCCESS) + { + found = route_entry_clone(&route); + this->routes->put(this->routes, found, found); + } + this->routes_lock->unlock(this->routes_lock); + return status; +} + +METHOD(kernel_net_t, del_route, status_t, + private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) +{ + status_t status; + route_entry_t *found, route = { + .dst_net = dst_net, + .prefixlen = prefixlen, + .gateway = gateway, + .if_name = if_name, + }; + + this->routes_lock->lock(this->routes_lock); + found = this->routes->get(this->routes, &route); + if (!found) + { + this->routes_lock->unlock(this->routes_lock); + return NOT_FOUND; + } + this->routes->remove(this->routes, found); + route_entry_destroy(found); + status = manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway, + if_name); + this->routes_lock->unlock(this->routes_lock); + return status; +} + +/** + * Do a route lookup for dest and return either the nexthop or the source + * address. + */ +static host_t *get_route(private_kernel_pfroute_net_t *this, bool nexthop, + host_t *dest, host_t *src) +{ + struct { + struct rt_msghdr hdr; + char buf[sizeof(struct sockaddr_storage) * RTAX_MAX]; + } msg = { + .hdr = { + .rtm_version = RTM_VERSION, + .rtm_type = RTM_GET, + .rtm_pid = this->pid, + .rtm_seq = ref_get(&this->seq), + }, + }; + host_t *host = NULL; + enumerator_t *enumerator; + struct sockaddr *addr; + bool failed = FALSE; + int type; + +retry: + msg.hdr.rtm_msglen = sizeof(struct rt_msghdr); + for (type = 0; type < RTAX_MAX; type++) + { + switch (type) + { + case RTAX_DST: + add_rt_addr(&msg.hdr, RTA_DST, dest); + break; + case RTAX_IFA: + add_rt_addr(&msg.hdr, RTA_IFA, src); + break; + case RTAX_IFP: + if (!nexthop) + { /* add an empty IFP to ensure we get a source address */ + add_rt_ifname(&msg.hdr, RTA_IFP, ""); + } + break; + default: + break; + } + } + this->mutex->lock(this->mutex); + + while (this->waiting_seq) + { + this->condvar->wait(this->condvar, this->mutex); + } + this->waiting_seq = msg.hdr.rtm_seq; + if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen) + { + while (TRUE) + { + if (this->condvar->timed_wait(this->condvar, this->mutex, 1000)) + { /* timed out? */ + break; + } + if (!this->reply) + { + continue; + } + enumerator = create_rtmsg_enumerator(this->reply); + while (enumerator->enumerate(enumerator, &type, &addr)) + { + if (nexthop) + { + if (type == RTAX_DST && this->reply->rtm_flags & RTF_HOST) + { /* probably a cloned/cached direct route, only use that + * as fallback if no gateway is found */ + host = host ?: host_create_from_sockaddr(addr); + } + if (type == RTAX_GATEWAY) + { /* could actually be a MAC address */ + host_t *gtw = host_create_from_sockaddr(addr); + if (gtw) + { + DESTROY_IF(host); + host = gtw; + } + } + } + else + { + if (type == RTAX_IFA) + { + host = host_create_from_sockaddr(addr); + } + } + } + enumerator->destroy(enumerator); + break; + } + } + else + { + failed = TRUE; + } + free(this->reply); + this->reply = NULL; + /* signal completion of query to a waiting thread */ + this->waiting_seq = 0; + this->condvar->signal(this->condvar); + this->mutex->unlock(this->mutex); + + if (failed) + { + if (src) + { /* the given source address might be gone, try again without */ + src = NULL; + msg.hdr.rtm_seq = ref_get(&this->seq); + msg.hdr.rtm_addrs = 0; + memset(msg.buf, 0, sizeof(msg.buf)); + goto retry; + } + DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno)); + } + if (nexthop) + { + host = host ?: dest->clone(dest); + } + else + { /* make sure the source address is not virtual and usable */ + addr_entry_t *entry, lookup = { + .ip = host, + }; + + if (!host) + { + return NULL; + } + this->lock->read_lock(this->lock); + entry = this->addrs->get_match(this->addrs, &lookup, + (void*)addr_map_entry_match_up_and_usable); + this->lock->unlock(this->lock); + if (!entry) + { + host->destroy(host); + return NULL; + } + } + DBG2(DBG_KNL, "using %H as %s to reach %H", host, + nexthop ? "nexthop" : "address", dest); + return host; +} + +METHOD(kernel_net_t, get_source_addr, host_t*, + private_kernel_pfroute_net_t *this, host_t *dest, host_t *src) +{ + return get_route(this, FALSE, dest, src); +} + +METHOD(kernel_net_t, get_nexthop, host_t*, + private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src) +{ + return get_route(this, TRUE, dest, src); +} + +/** + * Initialize a list of local addresses. + */ +static status_t init_address_list(private_kernel_pfroute_net_t *this) +{ + struct ifaddrs *ifap, *ifa; + iface_entry_t *iface, *current; + addr_entry_t *addr; + enumerator_t *ifaces, *addrs; + + DBG2(DBG_KNL, "known interfaces and IP addresses:"); + + if (getifaddrs(&ifap) < 0) + { + DBG1(DBG_KNL, " failed to get interfaces!"); + return FAILED; + } + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + { + continue; + } + switch(ifa->ifa_addr->sa_family) + { + case AF_LINK: + case AF_INET: + case AF_INET6: + { + iface = NULL; + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, ¤t)) + { + if (streq(current->ifname, ifa->ifa_name)) + { + iface = current; + break; + } + } + ifaces->destroy(ifaces); + + if (!iface) + { + INIT(iface, + .ifindex = if_nametoindex(ifa->ifa_name), + .flags = ifa->ifa_flags, + .addrs = linked_list_create(), + .usable = charon->kernel->is_interface_usable( + charon->kernel, ifa->ifa_name), + ); + memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ); + this->ifaces->insert_last(this->ifaces, iface); + } + + if (ifa->ifa_addr->sa_family != AF_LINK) + { + INIT(addr, + .ip = host_create_from_sockaddr(ifa->ifa_addr), + ); + iface->addrs->insert_last(iface->addrs, addr); + addr_map_entry_add(this, addr, iface); + } + } + } + } + freeifaddrs(ifap); + + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (iface->usable && iface->flags & IFF_UP) + { + DBG2(DBG_KNL, " %s", iface->ifname); + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, (void**)&addr)) + { + DBG2(DBG_KNL, " %H", addr->ip); + } + addrs->destroy(addrs); + } + } + ifaces->destroy(ifaces); + + return SUCCESS; +} + +METHOD(kernel_net_t, destroy, void, + private_kernel_pfroute_net_t *this) +{ + enumerator_t *enumerator; + route_entry_t *route; + addr_entry_t *addr; + + enumerator = this->routes->create_enumerator(this->routes); + while (enumerator->enumerate(enumerator, NULL, (void**)&route)) + { + manage_route(this, RTM_DELETE, route->dst_net, route->prefixlen, + route->gateway, route->if_name); + route_entry_destroy(route); + } + enumerator->destroy(enumerator); + this->routes->destroy(this->routes); + this->routes_lock->destroy(this->routes_lock); + + if (this->socket != -1) + { + lib->watcher->remove(lib->watcher, this->socket); + close(this->socket); + } + + net_changes_clear(this); + this->net_changes->destroy(this->net_changes); + this->net_changes_lock->destroy(this->net_changes_lock); + + enumerator = this->addrs->create_enumerator(this->addrs); + while (enumerator->enumerate(enumerator, NULL, (void**)&addr)) + { + free(addr); + } + enumerator->destroy(enumerator); + this->addrs->destroy(this->addrs); + this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy); + this->tuns->destroy(this->tuns); + this->lock->destroy(this->lock); + this->mutex->destroy(this->mutex); + this->condvar->destroy(this->condvar); + this->roam_lock->destroy(this->roam_lock); + free(this->reply); + free(this); +} + +/* + * Described in header. + */ +kernel_pfroute_net_t *kernel_pfroute_net_create() +{ + private_kernel_pfroute_net_t *this; + + INIT(this, + .public = { + .interface = { + .get_features = _get_features, + .get_interface = _get_interface_name, + .create_address_enumerator = _create_address_enumerator, + .get_source_addr = _get_source_addr, + .get_nexthop = _get_nexthop, + .add_ip = _add_ip, + .del_ip = _del_ip, + .add_route = _add_route, + .del_route = _del_route, + .destroy = _destroy, + }, + }, + .pid = getpid(), + .ifaces = linked_list_create(), + .addrs = hashtable_create( + (hashtable_hash_t)addr_map_entry_hash, + (hashtable_equals_t)addr_map_entry_equals, 16), + .routes = hashtable_create((hashtable_hash_t)route_entry_hash, + (hashtable_equals_t)route_entry_equals, 16), + .net_changes = hashtable_create( + (hashtable_hash_t)net_change_hash, + (hashtable_equals_t)net_change_equals, 16), + .tuns = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .routes_lock = mutex_create(MUTEX_TYPE_DEFAULT), + .net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT), + .roam_lock = spinlock_create(), + .vip_wait = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-pfroute.vip_wait", 1000, lib->ns), + .install_virtual_ip = lib->settings->get_bool(lib->settings, + "%s.install_virtual_ip", TRUE, lib->ns), + ); + timerclear(&this->last_route_reinstall); + timerclear(&this->next_roam); + + /* create a PF_ROUTE socket to communicate with the kernel */ + this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); + if (this->socket == -1) + { + DBG1(DBG_KNL, "unable to create PF_ROUTE socket"); + destroy(this); + return NULL; + } + + if (streq(lib->ns, "starter")) + { + /* starter has no threads, so we do not register for kernel events */ + if (shutdown(this->socket, SHUT_RD) != 0) + { + DBG1(DBG_KNL, "closing read end of PF_ROUTE socket failed: %s", + strerror(errno)); + } + } + else + { + lib->watcher->add(lib->watcher, this->socket, WATCHER_READ, + (watcher_cb_t)receive_events, this); + } + if (init_address_list(this) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get interface list"); + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +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..acd834ba3 --- /dev/null +++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "kernel_pfroute_plugin.h" + +#include "kernel_pfroute_net.h" + +typedef struct private_kernel_pfroute_plugin_t private_kernel_pfroute_plugin_t; + +/** + * private data of kernel PF_ROUTE plugin + */ +struct private_kernel_pfroute_plugin_t { + /** + * implements plugin interface + */ + kernel_pfroute_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_kernel_pfroute_plugin_t *this) +{ + return "kernel-pfroute"; +} + +METHOD(plugin_t, get_features, int, + private_kernel_pfroute_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(kernel_net_register, kernel_pfroute_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_kernel_pfroute_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *kernel_pfroute_plugin_create() +{ + private_kernel_pfroute_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h new file mode 100644 index 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY 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 + +typedef struct kernel_pfroute_plugin_t kernel_pfroute_plugin_t; + +/** + * PF_ROUTE kernel interface plugin + */ +struct kernel_pfroute_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** KERNEL_PFROUTE_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.am b/src/libcharon/plugins/kernel_wfp/Makefile.am index 85e5089a3..737a79b6c 100644 --- a/src/libcharon/plugins/kernel_wfp/Makefile.am +++ b/src/libcharon/plugins/kernel_wfp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in index efb214b88..cfe643f26 100644 --- a/src/libcharon/plugins/kernel_wfp/Makefile.in +++ b/src/libcharon/plugins/kernel_wfp/Makefile.in @@ -424,6 +424,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -439,7 +441,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c index 95f79f168..e1c429885 100644 --- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c +++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c @@ -20,7 +20,6 @@ #include "kernel_wfp_ipsec.h" #include -#include #include #include #include @@ -1396,10 +1395,9 @@ static bool uninstall_route(private_kernel_wfp_ipsec_t *this, { if (--route->refs == 0) { - if (hydra->kernel_interface->get_interface(hydra->kernel_interface, - src, &name)) + if (charon->kernel->get_interface(charon->kernel, src, &name)) { - res = hydra->kernel_interface->del_route(hydra->kernel_interface, + res = charon->kernel->del_route(charon->kernel, dst->get_address(dst), mask, gtw, src, name) == SUCCESS; free(name); } @@ -1442,10 +1440,9 @@ static bool install_route(private_kernel_wfp_ipsec_t *this, } else { - if (hydra->kernel_interface->get_interface(hydra->kernel_interface, - src, &name)) + if (charon->kernel->get_interface(charon->kernel, src, &name)) { - if (hydra->kernel_interface->add_route(hydra->kernel_interface, + if (charon->kernel->add_route(charon->kernel, dst->get_address(dst), mask, gtw, src, name) == SUCCESS) { INIT(route, @@ -1486,14 +1483,13 @@ static bool manage_route(private_kernel_wfp_ipsec_t *this, { return FALSE; } - if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface, - src_ts, &src, NULL) != SUCCESS) + if (charon->kernel->get_address_by_ts(charon->kernel, src_ts, &src, + NULL) != SUCCESS) { dst->destroy(dst); return FALSE; } - gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface, - remote, -1, local); + gtw = charon->kernel->get_nexthop(charon->kernel, remote, -1, local); if (add) { done = install_route(this, dst, mask, src, gtw); @@ -1650,8 +1646,7 @@ static void acquire(private_kernel_wfp_ipsec_t *this, UINT64 filter_id, { src = src ? src->clone(src) : NULL; dst = dst ? dst->clone(dst) : NULL; - hydra->kernel_interface->acquire(hydra->kernel_interface, reqid, - src, dst); + charon->kernel->acquire(charon->kernel, reqid, src, dst); } } @@ -2069,8 +2064,8 @@ static job_requeue_t expire_job(expire_data_t *data) if (entry) { - hydra->kernel_interface->expire(hydra->kernel_interface, protocol, - data->spi, data->dst, data->hard); + charon->kernel->expire(charon->kernel, protocol, data->spi, data->dst, + data->hard); } return JOB_REQUEUE_NONE; diff --git a/src/libcharon/plugins/led/Makefile.am b/src/libcharon/plugins/led/Makefile.am index 18d6af399..9868f9efa 100644 --- a/src/libcharon/plugins/led/Makefile.am +++ b/src/libcharon/plugins/led/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in index 7942868f6..63bbf1975 100644 --- a/src/libcharon/plugins/led/Makefile.in +++ b/src/libcharon/plugins/led/Makefile.in @@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -428,7 +430,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/load_tester/Makefile.am b/src/libcharon/plugins/load_tester/Makefile.am index 31e1b5c6f..af3adb257 100644 --- a/src/libcharon/plugins/load_tester/Makefile.am +++ b/src/libcharon/plugins/load_tester/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index 52dbec53f..14fcd6f4c 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -426,6 +426,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -441,7 +443,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index 8a500635c..8f6abde0c 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -656,8 +655,8 @@ static host_t *allocate_addr(private_load_tester_config_t *this, uint num) id->destroy(id); return NULL; } - if (hydra->kernel_interface->add_ip(hydra->kernel_interface, - found, this->prefix, iface) != SUCCESS) + if (charon->kernel->add_ip(charon->kernel, found, this->prefix, + iface) != SUCCESS) { DBG1(DBG_CFG, "installing load-tester IP %H on %s failed", found, iface); found->destroy(found); @@ -852,8 +851,8 @@ METHOD(load_tester_config_t, delete_ip, void, { if (pool->release_address(pool, entry->host, entry->id)) { - hydra->kernel_interface->del_ip(hydra->kernel_interface, - entry->host, this->prefix, FALSE); + charon->kernel->del_ip(charon->kernel, entry->host, + this->prefix, FALSE); break; } } @@ -882,8 +881,8 @@ static void cleanup_leases(private_load_tester_config_t *this) { if (online) { - hydra->kernel_interface->del_ip(hydra->kernel_interface, - addr, this->prefix, FALSE); + charon->kernel->del_ip(charon->kernel, addr, this->prefix, + FALSE); entry = this->leases->remove(this->leases, addr); if (entry) { diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index c7380b974..6cf3a909c 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -23,7 +23,6 @@ #include -#include #include #include #include @@ -240,16 +239,24 @@ METHOD(plugin_t, get_features, int, PLUGIN_SDEPEND(PRIVKEY, KEY_RSA), PLUGIN_SDEPEND(CERT_DECODE, CERT_ANY), PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + PLUGIN_CALLBACK(kernel_ipsec_register, load_tester_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), }; + int count = countof(f); + *features = f; - return countof(f); + + if (!lib->settings->get_bool(lib->settings, + "%s.plugins.load-tester.fake_kernel", FALSE, lib->ns)) + { + count -= 2; + } + return count; } METHOD(plugin_t, destroy, void, private_load_tester_plugin_t *this) { - hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface, - (kernel_ipsec_constructor_t)load_tester_ipsec_create); this->mutex->destroy(this->mutex); this->condvar->destroy(this->condvar); free(this); @@ -289,12 +296,5 @@ plugin_t *load_tester_plugin_create() .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), ); - - if (lib->settings->get_bool(lib->settings, - "%s.plugins.load-tester.fake_kernel", FALSE, lib->ns)) - { - hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, - (kernel_ipsec_constructor_t)load_tester_ipsec_create); - } return &this->public.plugin; } diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am index 223654ea9..623275b21 100644 --- a/src/libcharon/plugins/lookip/Makefile.am +++ b/src/libcharon/plugins/lookip/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in index 264c58ff5..9b56d94fe 100644 --- a/src/libcharon/plugins/lookip/Makefile.in +++ b/src/libcharon/plugins/lookip/Makefile.in @@ -422,6 +422,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -437,7 +439,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am index fe5c963fd..02c283f5b 100644 --- a/src/libcharon/plugins/maemo/Makefile.am +++ b/src/libcharon/plugins/maemo/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in index 76c9012b2..5cc654967 100644 --- a/src/libcharon/plugins/maemo/Makefile.in +++ b/src/libcharon/plugins/maemo/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/medcli/Makefile.am b/src/libcharon/plugins/medcli/Makefile.am index cfa825980..0408c8963 100644 --- a/src/libcharon/plugins/medcli/Makefile.am +++ b/src/libcharon/plugins/medcli/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index 35740c369..32c428487 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/medsrv/Makefile.am b/src/libcharon/plugins/medsrv/Makefile.am index f21220260..1d1cb4465 100644 --- a/src/libcharon/plugins/medsrv/Makefile.am +++ b/src/libcharon/plugins/medsrv/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index 8fe160ef3..de0217a80 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/osx_attr/Makefile.am b/src/libcharon/plugins/osx_attr/Makefile.am index aa1d46290..908aa8806 100644 --- a/src/libcharon/plugins/osx_attr/Makefile.am +++ b/src/libcharon/plugins/osx_attr/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in index 9a5e438e1..6a1a81f08 100644 --- a/src/libcharon/plugins/osx_attr/Makefile.in +++ b/src/libcharon/plugins/osx_attr/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/p_cscf/Makefile.am b/src/libcharon/plugins/p_cscf/Makefile.am new file mode 100644 index 000000000..1e00a56a8 --- /dev/null +++ b/src/libcharon/plugins/p_cscf/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-p-cscf.la +else +plugin_LTLIBRARIES = libstrongswan-p-cscf.la +endif + +libstrongswan_p_cscf_la_SOURCES = \ + p_cscf_plugin.c p_cscf_plugin.h \ + p_cscf_handler.c p_cscf_handler.h + +libstrongswan_p_cscf_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/p_cscf/Makefile.in b/src/libcharon/plugins/p_cscf/Makefile.in new file mode 100644 index 000000000..7f78db85a --- /dev/null +++ b/src/libcharon/plugins/p_cscf/Makefile.in @@ -0,0 +1,782 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/p_cscf +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_p_cscf_la_LIBADD = +am_libstrongswan_p_cscf_la_OBJECTS = p_cscf_plugin.lo \ + p_cscf_handler.lo +libstrongswan_p_cscf_la_OBJECTS = \ + $(am_libstrongswan_p_cscf_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_p_cscf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_p_cscf_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_p_cscf_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_p_cscf_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_p_cscf_la_SOURCES) +DIST_SOURCES = $(libstrongswan_p_cscf_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-p-cscf.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-p-cscf.la +libstrongswan_p_cscf_la_SOURCES = \ + p_cscf_plugin.c p_cscf_plugin.h \ + p_cscf_handler.c p_cscf_handler.h + +libstrongswan_p_cscf_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/p_cscf/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/p_cscf/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-p-cscf.la: $(libstrongswan_p_cscf_la_OBJECTS) $(libstrongswan_p_cscf_la_DEPENDENCIES) $(EXTRA_libstrongswan_p_cscf_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_p_cscf_la_LINK) $(am_libstrongswan_p_cscf_la_rpath) $(libstrongswan_p_cscf_la_OBJECTS) $(libstrongswan_p_cscf_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/p_cscf_handler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/p_cscf_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pluginLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.c b/src/libcharon/plugins/p_cscf/p_cscf_handler.c new file mode 100644 index 000000000..76633845e --- /dev/null +++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "p_cscf_handler.h" + +#include +#include + +typedef struct private_p_cscf_handler_t private_p_cscf_handler_t; + +/** + * Private data + */ +struct private_p_cscf_handler_t { + + /** + * Public interface + */ + p_cscf_handler_t public; +}; + +METHOD(attribute_handler_t, handle, bool, + private_p_cscf_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + host_t *server; + int family = AF_INET6; + + switch (type) + { + case P_CSCF_IP4_ADDRESS: + family = AF_INET; + /* fall-through */ + case P_CSCF_IP6_ADDRESS: + server = host_create_from_chunk(family, data, 0); + if (!server) + { + DBG1(DBG_CFG, "received invalid P-CSCF server IP"); + return FALSE; + } + DBG1(DBG_CFG, "received P-CSCF server IP %H", server); + server->destroy(server); + return TRUE; + default: + return FALSE; + } +} + +METHOD(attribute_handler_t, release, void, + private_p_cscf_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case P_CSCF_IP4_ADDRESS: + case P_CSCF_IP6_ADDRESS: + /* nothing to do as we only log the server IPs */ + break; + default: + break; + } +} + +/** + * Data for attribute enumerator + */ +typedef struct { + enumerator_t public; + bool request_ipv4; + bool request_ipv6; +} attr_enumerator_t; + +METHOD(enumerator_t, enumerate_attrs, bool, + attr_enumerator_t *this, configuration_attribute_type_t *type, + chunk_t *data) +{ + if (this->request_ipv4) + { + *type = P_CSCF_IP4_ADDRESS; + *data = chunk_empty; + this->request_ipv4 = FALSE; + return TRUE; + } + if (this->request_ipv6) + { + *type = P_CSCF_IP6_ADDRESS; + *data = chunk_empty; + this->request_ipv6 = FALSE; + return TRUE; + } + return FALSE; +} + +/** + * Check if the given host has a matching address family + */ +static bool is_family(host_t *host, int *family) +{ + return host->get_family(host) == *family; +} + +/** + * Check if a list has a host of a given family + */ +static bool has_host_family(linked_list_t *list, int family) +{ + return list->find_first(list, (void*)is_family, NULL, &family) == SUCCESS; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, + private_p_cscf_handler_t *this, ike_sa_t *ike_sa, + linked_list_t *vips) +{ + attr_enumerator_t *enumerator; + + if (ike_sa->get_version(ike_sa) == IKEV1) + { + return enumerator_create_empty(); + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_attrs, + .destroy = (void*)free, + }, + ); + if (lib->settings->get_bool(lib->settings, "%s.plugins.p-cscf.enable.%s", + FALSE, lib->ns, ike_sa->get_name(ike_sa))) + { + enumerator->request_ipv4 = has_host_family(vips, AF_INET); + enumerator->request_ipv6 = has_host_family(vips, AF_INET6); + } + return &enumerator->public; +} + +METHOD(p_cscf_handler_t, destroy, void, + private_p_cscf_handler_t *this) +{ + free(this); +} + +/** + * See header + */ +p_cscf_handler_t *p_cscf_handler_create() +{ + private_p_cscf_handler_t *this; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = _release, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.h b/src/libcharon/plugins/p_cscf/p_cscf_handler.h new file mode 100644 index 000000000..ad4f1acce --- /dev/null +++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup p_cscf_handler p_cscf_handler + * @{ @ingroup p_cscf + */ + +#ifndef P_CSCF_HANDLER_H_ +#define P_CSCF_HANDLER_H_ + +#include + +typedef struct p_cscf_handler_t p_cscf_handler_t; + +/** + * Attribute handler for P-CSCF server addresses. + */ +struct p_cscf_handler_t { + + /** + * Implements attribute_handler_t. + */ + attribute_handler_t handler; + + /** + * Destroy a p_cscf_handler_t. + */ + void (*destroy)(p_cscf_handler_t *this); +}; + +/** + * Create an p_cscf_handler_t instance. + */ +p_cscf_handler_t *p_cscf_handler_create(); + +#endif /** P_CSCF_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/p_cscf/p_cscf_plugin.c b/src/libcharon/plugins/p_cscf/p_cscf_plugin.c new file mode 100644 index 000000000..8e2bc727e --- /dev/null +++ b/src/libcharon/plugins/p_cscf/p_cscf_plugin.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "p_cscf_plugin.h" +#include "p_cscf_handler.h" + +#include + +typedef struct private_p_cscf_plugin_t private_p_cscf_plugin_t; + +/** + * Private data + */ +struct private_p_cscf_plugin_t { + + /** + * Public interface + */ + p_cscf_plugin_t public; + + /** + * P-CSCF server address attribute handler + */ + p_cscf_handler_t *handler; +}; + +METHOD(plugin_t, get_name, char*, + private_p_cscf_plugin_t *this) +{ + return "p-cscf"; +} + +/** + * Register handler + */ +static bool plugin_cb(private_p_cscf_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); + } + else + { + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_p_cscf_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "p-cscf"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_p_cscf_plugin_t *this) +{ + this->handler->destroy(this->handler); + free(this); +} + +/** + * See header + */ +plugin_t *p_cscf_plugin_create() +{ + private_p_cscf_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .handler = p_cscf_handler_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/p_cscf/p_cscf_plugin.h b/src/libcharon/plugins/p_cscf/p_cscf_plugin.h new file mode 100644 index 000000000..51b17674d --- /dev/null +++ b/src/libcharon/plugins/p_cscf/p_cscf_plugin.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup p_cscf p_cscf + * @ingroup cplugins + * + * @defgroup p_cscf_plugin p_cscf_plugin + * @{ @ingroup p_cscf + */ + +#ifndef P_CSCF_PLUGIN_H_ +#define P_CSCF_PLUGIN_H_ + +#include + +typedef struct p_cscf_plugin_t p_cscf_plugin_t; + +/** + * Plugin that requests P-CSCF server addresses from an ePDG as specified + * in RFC 7651. + */ +struct p_cscf_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** P_CSCF_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/radattr/Makefile.am b/src/libcharon/plugins/radattr/Makefile.am index 15d5a0a1f..74d9351f2 100644 --- a/src/libcharon/plugins/radattr/Makefile.am +++ b/src/libcharon/plugins/radattr/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in index baff3fc76..3f39ba237 100644 --- a/src/libcharon/plugins/radattr/Makefile.in +++ b/src/libcharon/plugins/radattr/Makefile.in @@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am index 9cfc370c0..d3d4e73cf 100644 --- a/src/libcharon/plugins/resolve/Makefile.am +++ b/src/libcharon/plugins/resolve/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DRESOLV_CONF=\"${resolv_conf}\" diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in index 91479bf52..70d97cc32 100644 --- a/src/libcharon/plugins/resolve/Makefile.in +++ b/src/libcharon/plugins/resolve/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DRESOLV_CONF=\"${resolv_conf}\" diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c index 74c3960ff..ec3decc4d 100644 --- a/src/libcharon/plugins/resolve/resolve_handler.c +++ b/src/libcharon/plugins/resolve/resolve_handler.c @@ -20,7 +20,6 @@ #include #include -#include #include #include diff --git a/src/libcharon/plugins/smp/Makefile.am b/src/libcharon/plugins/smp/Makefile.am index 3aa533e56..252db32a6 100644 --- a/src/libcharon/plugins/smp/Makefile.am +++ b/src/libcharon/plugins/smp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index 572e7fc2f..221cda71a 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index 2aa061fd2..56b19c792 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -229,8 +229,8 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer local = ike_sa->get_my_host(ike_sa); xmlTextWriterStartElement(writer, "local"); xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx", - id->is_initiator(id) ? id->get_initiator_spi(id) - : id->get_responder_spi(id)); + be64toh(id->is_initiator(id) ? id->get_initiator_spi(id) + : id->get_responder_spi(id))); write_id(writer, "identification", ike_sa->get_my_id(ike_sa)); write_address(writer, "address", local); xmlTextWriterWriteFormatElement(writer, "port", "%d", @@ -246,8 +246,8 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer remote = ike_sa->get_other_host(ike_sa); xmlTextWriterStartElement(writer, "remote"); xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx", - id->is_initiator(id) ? id->get_responder_spi(id) - : id->get_initiator_spi(id)); + be64toh(id->is_initiator(id) ? id->get_responder_spi(id) + : id->get_initiator_spi(id))); write_id(writer, "identification", ike_sa->get_other_id(ike_sa)); write_address(writer, "address", remote); xmlTextWriterWriteFormatElement(writer, "port", "%d", diff --git a/src/libcharon/plugins/socket_default/Makefile.am b/src/libcharon/plugins/socket_default/Makefile.am index e524ffd18..7231703b3 100644 --- a/src/libcharon/plugins/socket_default/Makefile.am +++ b/src/libcharon/plugins/socket_default/Makefile.am @@ -1,7 +1,6 @@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index 25b40995b..3dcfaf4a6 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 13bf3e775..6e432d9cf 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -720,16 +719,15 @@ static int open_socket(private_socket_default_socket_t *this, } #endif - if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface, - skt, family)) + if (!charon->kernel->bypass_socket(charon->kernel, skt, family)) { DBG1(DBG_NET, "installing IKE bypass policy failed"); } /* enable UDP decapsulation for NAT-T sockets */ if (port == &this->natt && - !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, - skt, family, this->natt)) + !charon->kernel->enable_udp_decap(charon->kernel, skt, family, + this->natt)) { DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed", family == AF_INET ? "IPv4" : "IPv6", this->natt); diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.am b/src/libcharon/plugins/socket_dynamic/Makefile.am index a1e21b98b..087ebb728 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.am +++ b/src/libcharon/plugins/socket_dynamic/Makefile.am @@ -1,7 +1,6 @@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 5c010a59a..88bc22f5e 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index a032134c3..b89cae47b 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -438,15 +437,13 @@ static int open_socket(private_socket_dynamic_socket_t *this, return 0; } - if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface, - fd, family)) + if (!charon->kernel->bypass_socket(charon->kernel, fd, family)) { DBG1(DBG_NET, "installing IKE bypass policy failed"); } /* enable UDP decapsulation on each socket */ - if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, - fd, family, *port)) + if (!charon->kernel->enable_udp_decap(charon->kernel, fd, family, *port)) { DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed", family == AF_INET ? "IPv4" : "IPv6", *port); diff --git a/src/libcharon/plugins/socket_win/Makefile.am b/src/libcharon/plugins/socket_win/Makefile.am index f01178fcc..293d9bc9f 100644 --- a/src/libcharon/plugins/socket_win/Makefile.am +++ b/src/libcharon/plugins/socket_win/Makefile.am @@ -1,7 +1,6 @@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in index 0c3bf31b9..683011062 100644 --- a/src/libcharon/plugins/socket_win/Makefile.in +++ b/src/libcharon/plugins/socket_win/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c index fbfbedae1..94af08e80 100644 --- a/src/libcharon/plugins/socket_win/socket_win_socket.c +++ b/src/libcharon/plugins/socket_win/socket_win_socket.c @@ -19,7 +19,6 @@ #include "socket_win_socket.h" #include -#include #include #include @@ -397,13 +396,11 @@ static SOCKET open_socket(private_socket_win_socket_t *this, int i) closesocket(s); return INVALID_SOCKET; } - if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface, - s, AF_INET)) + if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET)) { DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed"); } - if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface, - s, AF_INET6)) + if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET6)) { DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed"); } diff --git a/src/libcharon/plugins/sql/Makefile.am b/src/libcharon/plugins/sql/Makefile.am index c947db892..44a3d5f4a 100644 --- a/src/libcharon/plugins/sql/Makefile.am +++ b/src/libcharon/plugins/sql/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index f74257af2..b09379b02 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am index b90688791..26edc3dcd 100644 --- a/src/libcharon/plugins/stroke/Makefile.am +++ b/src/libcharon/plugins/stroke/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/stroke \ -DIPSEC_CONFDIR=\"${sysconfdir}\" \ diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index a316f5c25..2b22b333a 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/stroke \ -DIPSEC_CONFDIR=\"${sysconfdir}\" \ diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 68cf83089..d0eb2aac3 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -16,7 +16,6 @@ #include "stroke_config.h" -#include #include #include #include @@ -201,8 +200,7 @@ static bool is_local(char *address, bool any_allowed) host = host_create_from_dns(token, 0, 0); if (host) { - if (hydra->kernel_interface->get_interface( - hydra->kernel_interface, host, NULL)) + if (charon->kernel->get_interface(charon->kernel, host, NULL)) { found = TRUE; } @@ -312,117 +310,6 @@ static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy) } } -/** - * Parse public key / signature strength constraints - */ -static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) -{ - enumerator_t *enumerator; - bool rsa = FALSE, ecdsa = FALSE, bliss = FALSE, - rsa_len = FALSE, ecdsa_len = FALSE, bliss_strength = FALSE; - int strength; - char *token; - - enumerator = enumerator_create_token(auth, "-", ""); - while (enumerator->enumerate(enumerator, &token)) - { - bool found = FALSE; - int i; - struct { - char *name; - signature_scheme_t scheme; - key_type_t key; - } schemes[] = { - { "md5", SIGN_RSA_EMSA_PKCS1_MD5, KEY_RSA, }, - { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1, KEY_RSA, }, - { "sha224", SIGN_RSA_EMSA_PKCS1_SHA224, KEY_RSA, }, - { "sha256", SIGN_RSA_EMSA_PKCS1_SHA256, KEY_RSA, }, - { "sha384", SIGN_RSA_EMSA_PKCS1_SHA384, KEY_RSA, }, - { "sha512", SIGN_RSA_EMSA_PKCS1_SHA512, KEY_RSA, }, - { "sha1", SIGN_ECDSA_WITH_SHA1_DER, KEY_ECDSA, }, - { "sha256", SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, }, - { "sha384", SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, }, - { "sha512", SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, }, - { "sha256", SIGN_ECDSA_256, KEY_ECDSA, }, - { "sha384", SIGN_ECDSA_384, KEY_ECDSA, }, - { "sha512", SIGN_ECDSA_521, KEY_ECDSA, }, - { "sha256", SIGN_BLISS_WITH_SHA2_256, KEY_BLISS, }, - { "sha384", SIGN_BLISS_WITH_SHA2_384, KEY_BLISS, }, - { "sha512", SIGN_BLISS_WITH_SHA2_512, KEY_BLISS, }, - }; - - if (rsa_len || ecdsa_len || bliss_strength) - { /* expecting a key strength token */ - strength = atoi(token); - if (strength) - { - if (rsa_len) - { - cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength); - } - else if (ecdsa_len) - { - cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength); - } - else if (bliss_strength) - { - cfg->add(cfg, AUTH_RULE_BLISS_STRENGTH, (uintptr_t)strength); - } - } - rsa_len = ecdsa_len = bliss_strength = FALSE; - if (strength) - { - continue; - } - } - if (streq(token, "rsa")) - { - rsa = rsa_len = TRUE; - continue; - } - if (streq(token, "ecdsa")) - { - ecdsa = ecdsa_len = TRUE; - continue; - } - if (streq(token, "bliss")) - { - bliss = bliss_strength = TRUE; - continue; - } - if (streq(token, "pubkey")) - { - continue; - } - - for (i = 0; i < countof(schemes); i++) - { - if (streq(schemes[i].name, token)) - { - /* for each matching string, allow the scheme, if: - * - it is an RSA scheme, and we enforced RSA - * - it is an ECDSA scheme, and we enforced ECDSA - * - it is not a key type specific scheme - */ - if ((rsa && schemes[i].key == KEY_RSA) || - (ecdsa && schemes[i].key == KEY_ECDSA) || - (bliss && schemes[i].key == KEY_BLISS) || - (!rsa && !ecdsa && !bliss)) - { - cfg->add(cfg, AUTH_RULE_SIGNATURE_SCHEME, - (uintptr_t)schemes[i].scheme); - } - found = TRUE; - } - } - if (!found) - { - DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token); - } - } - enumerator->destroy(enumerator); -} - /** * build authentication config */ @@ -619,15 +506,15 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } /* authentication metod (class, actually) */ - if (strpfx(auth, "pubkey") || + if (strpfx(auth, "ike:") || + strpfx(auth, "pubkey") || strpfx(auth, "rsa") || strpfx(auth, "ecdsa") || strpfx(auth, "bliss")) { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); build_crl_policy(cfg, local, msg->add_conn.crl_policy); - - parse_pubkey_constraints(auth, cfg); + cfg->add_pubkey_constraints(cfg, auth, TRUE); } else if (streq(auth, "psk") || streq(auth, "secret")) { @@ -660,7 +547,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, if (pos) { *pos = 0; - parse_pubkey_constraints(pos + 1, cfg); + cfg->add_pubkey_constraints(cfg, pos + 1, FALSE); } type = eap_vendor_type_from_string(auth); if (type) diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index 5a1a5074d..36da5ff21 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -16,7 +16,6 @@ #include "stroke_control.h" -#include #include #include diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index c0192b5c0..0371c7032 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -2,6 +2,9 @@ * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -23,22 +26,12 @@ #include #endif /* HAVE_MALLINFO */ -#include #include #include #include #include -#include -#include -#include +#include #include -#include -#include - -/* 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; @@ -68,6 +61,11 @@ struct private_stroke_list_t { stroke_attribute_t *attribute; }; +/** + * Static certificate printer object + */ +static certificate_printer_t *cert_printer = NULL; + /** * Log tasks of a specific queue to out */ @@ -139,8 +137,10 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), ike_version_names, ike_sa->get_version(ike_sa), - id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "", - id->get_responder_spi(id), id->is_initiator(id) ? "" : "*"); + be64toh(id->get_initiator_spi(id)), + id->is_initiator(id) ? "*" : "", + be64toh(id->get_responder_spi(id)), + id->is_initiator(id) ? "" : "*"); if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED) @@ -244,40 +244,36 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) proposal = child_sa->get_proposal(child_sa); if (proposal) { - u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED; - u_int16_t encr_size = 0, int_size = 0; - u_int16_t esn = NO_EXT_SEQ_NUMBERS; + u_int16_t alg, ks; bool first = TRUE; - proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, - &encr_alg, &encr_size); - proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, - &int_alg, &int_size); - proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, - &esn, NULL); - - if (encr_alg != ENCR_UNDEFINED) + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, + &alg, &ks) && alg != ENCR_UNDEFINED) { - fprintf(out, "%N", encryption_algorithm_names, encr_alg); + fprintf(out, "%N", encryption_algorithm_names, alg); first = FALSE; - if (encr_size) + if (ks) { - fprintf(out, "_%u", encr_size); + fprintf(out, "_%u", ks); } } - if (int_alg != AUTH_UNDEFINED) + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, + &alg, &ks) && alg != AUTH_UNDEFINED) { - if (!first) - { - fprintf(out, "/"); - } - fprintf(out, "%N", integrity_algorithm_names, int_alg); - if (int_size) + fprintf(out, "%s%N", first ? "" : "/", + integrity_algorithm_names, alg); + if (ks) { - fprintf(out, "_%u", int_size); + fprintf(out, "_%u", ks); } } - if (esn == EXT_SEQ_NUMBERS) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, + &alg, NULL)) + { + fprintf(out, "/%N", diffie_hellman_group_names, alg); + } + if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, + &alg, NULL) && alg == EXT_SEQ_NUMBERS) { fprintf(out, "/ESN"); } @@ -538,8 +534,8 @@ METHOD(stroke_list_t, status, void, } enumerator->destroy(enumerator); - enumerator = hydra->kernel_interface->create_address_enumerator( - hydra->kernel_interface, ADDR_TYPE_REGULAR); + enumerator = charon->kernel->create_address_enumerator(charon->kernel, + ADDR_TYPE_REGULAR); fprintf(out, "Listening IP addresses:\n"); while (enumerator->enumerate(enumerator, (void**)&host)) { @@ -738,14 +734,20 @@ static linked_list_t* create_unique_cert_list(certificate_type_t type) } /** - * Print a single public key. + * Is there a matching private key? */ -static void list_public_key(public_key_t *public, FILE *out) +static bool has_privkey(certificate_t *cert) { + public_key_t *public; private_key_t *private = NULL; chunk_t keyid; identification_t *id; + public = cert->get_public_key(cert); + if (!public) + { + return FALSE; + } if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid)) { id = identification_create_from_encoding(ID_KEY_ID, keyid); @@ -753,521 +755,56 @@ static void list_public_key(public_key_t *public, FILE *out) public->get_type(public), id, NULL); id->destroy(id); } - - fprintf(out, " pubkey: %N %d bits%s\n", - key_type_names, public->get_type(public), - public->get_keysize(public), - private ? ", has private key" : ""); - if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid)) - { - fprintf(out, " keyid: %#B\n", &keyid); - } - if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid)) - { - fprintf(out, " subjkey: %#B\n", &keyid); - } + public->destroy(public); DESTROY_IF(private); -} - -/** - * list all raw public keys - */ -static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out) -{ - bool first = TRUE; - time_t now = time(NULL), notBefore, notAfter; - enumerator_t *enumerator; - certificate_t *cert; - - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, (void**)&cert)) - { - identification_t *subject = cert->get_subject(cert); - public_key_t *public = cert->get_public_key(cert); - - if (public) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of Raw Public Keys:\n"); - first = FALSE; - } - fprintf(out, "\n"); - - /* list subject if available */ - if (subject->get_type(subject) != ID_KEY_ID) - { - fprintf(out, " subject: %#Y\n", subject); - } - - /* list validity if available*/ - cert->get_validity(cert, &now, ¬Before, ¬After); - if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME) - { - fprintf(out, " validity: not before %T, ", ¬Before, utc); - if (now < notBefore) - { - fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); - } - else - { - fprintf(out, "ok\n"); - } - fprintf(out, " not after %T, ", ¬After, utc); - if (now > notAfter) - { - fprintf(out, "expired (%V ago)\n", &now, ¬After); - } - else - { - fprintf(out, "ok"); - if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %V)", &now, ¬After); - } - fprintf(out, " \n"); - } - } - - list_public_key(public, out); - public->destroy(public); - } - } - enumerator->destroy(enumerator); -} - -/** - * list OpenPGP certificates - */ -static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out) -{ - bool first = TRUE; - time_t now = time(NULL); - enumerator_t *enumerator = list->create_enumerator(list); - certificate_t *cert; - - while (enumerator->enumerate(enumerator, (void**)&cert)) - { - time_t created, until; - public_key_t *public; - pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert; - chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert); - - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of PGP End Entity Certificates:\n"); - first = FALSE; - } - fprintf(out, "\n"); - fprintf(out, " userid: '%Y'\n", cert->get_subject(cert)); - - fprintf(out, " digest: %#B\n", &fingerprint); - - /* list validity */ - cert->get_validity(cert, &now, &created, &until); - fprintf(out, " created: %T\n", &created, utc); - fprintf(out, " until: %T%s\n", &until, utc, - (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":""); - - public = cert->get_public_key(cert); - if (public) - { - list_public_key(public, out); - public->destroy(public); - } - } - enumerator->destroy(enumerator); + return (private != NULL); } /** * list all X.509 certificates matching the flags */ -static void stroke_list_certs(linked_list_t *list, char *label, - x509_flag_t flags, bool utc, FILE *out) +static void stroke_list_x509_certs(linked_list_t *list, x509_flag_t flag) { - bool first = TRUE; - time_t now = time(NULL); enumerator_t *enumerator; certificate_t *cert; - x509_flag_t flag_mask; - - /* mask all auxiliary flags */ - flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH | X509_IKE_INTERMEDIATE | - X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS); enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, (void**)&cert)) { x509_t *x509 = (x509_t*)cert; - x509_flag_t x509_flags = x509->get_flags(x509) & flag_mask; + x509_flag_t flags = x509->get_flags(x509) & X509_ANY; /* list only if flag is set or flag == 0 */ - if ((x509_flags & flags) || (x509_flags == flags)) + if ((flags & flag) || flags == flag) { - enumerator_t *enumerator; - identification_t *altName; - bool first_altName = TRUE; - u_int pathlen; - chunk_t serial, authkey; - time_t notBefore, notAfter; - public_key_t *public; - - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of %s:\n", label); - first = FALSE; - } - fprintf(out, "\n"); - - /* list subjectAltNames */ - enumerator = x509->create_subjectAltName_enumerator(x509); - while (enumerator->enumerate(enumerator, (void**)&altName)) - { - if (first_altName) - { - fprintf(out, " altNames: "); - first_altName = FALSE; - } - else - { - fprintf(out, ", "); - } - fprintf(out, "%Y", altName); - } - if (!first_altName) - { - fprintf(out, "\n"); - } - enumerator->destroy(enumerator); - - fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert)); - fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); - serial = chunk_skip_zero(x509->get_serial(x509)); - fprintf(out, " serial: %#B\n", &serial); - - /* list validity */ - cert->get_validity(cert, &now, ¬Before, ¬After); - fprintf(out, " validity: not before %T, ", ¬Before, utc); - if (now < notBefore) - { - fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); - } - else - { - fprintf(out, "ok\n"); - } - fprintf(out, " not after %T, ", ¬After, utc); - if (now > notAfter) - { - fprintf(out, "expired (%V ago)\n", &now, ¬After); - } - else - { - fprintf(out, "ok"); - if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %V)", &now, ¬After); - } - fprintf(out, " \n"); - } - - public = cert->get_public_key(cert); - if (public) - { - list_public_key(public, out); - public->destroy(public); - } - - /* list optional authorityKeyIdentifier */ - authkey = x509->get_authKeyIdentifier(x509); - if (authkey.ptr) - { - fprintf(out, " authkey: %#B\n", &authkey); - } - - /* list optional pathLenConstraint */ - pathlen = x509->get_constraint(x509, X509_PATH_LEN); - if (pathlen != X509_NO_CONSTRAINT) - { - fprintf(out, " pathlen: %u\n", pathlen); - } - - /* list optional ipAddrBlocks */ - if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS) - { - traffic_selector_t *ipAddrBlock; - bool first_ipAddrBlock = TRUE; - - fprintf(out, " addresses: "); - enumerator = x509->create_ipAddrBlock_enumerator(x509); - while (enumerator->enumerate(enumerator, &ipAddrBlock)) - { - if (first_ipAddrBlock) - { - first_ipAddrBlock = FALSE; - } - else - { - fprintf(out, ", "); - } - fprintf(out, "%R", ipAddrBlock); - } - enumerator->destroy(enumerator); - fprintf(out, "\n"); - } + cert_printer->print_caption(cert_printer, CERT_X509, flag); + cert_printer->print(cert_printer, cert, has_privkey(cert)); } } enumerator->destroy(enumerator); } /** - * list all X.509 attribute certificates + * list all other certificates types */ -static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) +static void stroke_list_other_certs(certificate_type_t type) { - bool first = TRUE; - time_t notBefore, notAfter, now = time(NULL); enumerator_t *enumerator; certificate_t *cert; + linked_list_t *list; + + list = create_unique_cert_list(type); enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &cert)) { - ac_t *ac = (ac_t*)cert; - ac_group_type_t type; - identification_t *id; - enumerator_t *groups; - chunk_t chunk; - bool firstgroup = TRUE; - - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 Attribute Certificates:\n"); - first = FALSE; - } - fprintf(out, "\n"); - - id = cert->get_subject(cert); - if (id) - { - fprintf(out, " holder: \"%Y\"\n", id); - } - id = ac->get_holderIssuer(ac); - if (id) - { - fprintf(out, " hissuer: \"%Y\"\n", id); - } - chunk = chunk_skip_zero(ac->get_holderSerial(ac)); - if (chunk.ptr) - { - fprintf(out, " hserial: %#B\n", &chunk); - } - groups = ac->create_group_enumerator(ac); - while (groups->enumerate(groups, &type, &chunk)) - { - int oid; - char *str; - - if (firstgroup) - { - fprintf(out, " groups: "); - firstgroup = FALSE; - } - else - { - fprintf(out, " "); - } - switch (type) - { - case AC_GROUP_TYPE_STRING: - fprintf(out, "%.*s", (int)chunk.len, chunk.ptr); - break; - case AC_GROUP_TYPE_OID: - oid = asn1_known_oid(chunk); - if (oid == OID_UNKNOWN) - { - str = asn1_oid_to_string(chunk); - if (str) - { - fprintf(out, "%s", str); - free(str); - } - else - { - fprintf(out, "OID:%#B", &chunk); - } - } - else - { - fprintf(out, "%s", oid_names[oid].name); - } - break; - case AC_GROUP_TYPE_OCTETS: - fprintf(out, "%#B", &chunk); - break; - } - fprintf(out, "\n"); - } - groups->destroy(groups); - fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); - chunk = chunk_skip_zero(ac->get_serial(ac)); - fprintf(out, " serial: %#B\n", &chunk); - - /* list validity */ - cert->get_validity(cert, &now, ¬Before, ¬After); - fprintf(out, " validity: not before %T, ", ¬Before, utc); - if (now < notBefore) - { - fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); - } - else - { - fprintf(out, "ok\n"); - } - fprintf(out, " not after %T, ", ¬After, utc); - if (now > notAfter) - { - fprintf(out, "expired (%V ago)\n", &now, ¬After); - } - else - { - fprintf(out, "ok"); - if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %V)", &now, ¬After); - } - fprintf(out, " \n"); - } - - /* list optional authorityKeyIdentifier */ - chunk = ac->get_authKeyIdentifier(ac); - if (chunk.ptr) - { - fprintf(out, " authkey: %#B\n", &chunk); - } + cert_printer->print_caption(cert_printer, cert->get_type(cert), X509_NONE); + cert_printer->print(cert_printer, cert, has_privkey(cert)); } enumerator->destroy(enumerator); -} - -/** - * list all X.509 CRLs - */ -static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out) -{ - bool first = TRUE; - time_t thisUpdate, nextUpdate, now = time(NULL); - enumerator_t *enumerator = list->create_enumerator(list); - certificate_t *cert; - while (enumerator->enumerate(enumerator, (void**)&cert)) - { - crl_t *crl = (crl_t*)cert; - chunk_t chunk; - - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 CRLs:\n"); - first = FALSE; - } - fprintf(out, "\n"); - - fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); - - /* list optional crlNumber */ - chunk = chunk_skip_zero(crl->get_serial(crl)); - if (chunk.ptr) - { - fprintf(out, " serial: %#B\n", &chunk); - } - if (crl->is_delta_crl(crl, &chunk)) - { - chunk = chunk_skip_zero(chunk); - fprintf(out, " delta for: %#B\n", &chunk); - } - - /* count the number of revoked certificates */ - { - int count = 0; - enumerator_t *enumerator = crl->create_enumerator(crl); - - while (enumerator->enumerate(enumerator, NULL, NULL, NULL)) - { - count++; - } - fprintf(out, " revoked: %d certificate%s\n", count, - (count == 1)? "" : "s"); - enumerator->destroy(enumerator); - } - - /* list validity */ - cert->get_validity(cert, &now, &thisUpdate, &nextUpdate); - fprintf(out, " updates: this %T\n", &thisUpdate, utc); - fprintf(out, " next %T, ", &nextUpdate, utc); - if (now > nextUpdate) - { - fprintf(out, "expired (%V ago)\n", &now, &nextUpdate); - } - else - { - fprintf(out, "ok"); - if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %V)", &now, &nextUpdate); - } - fprintf(out, " \n"); - } - - /* list optional authorityKeyIdentifier */ - chunk = crl->get_authKeyIdentifier(crl); - if (chunk.ptr) - { - fprintf(out, " authkey: %#B\n", &chunk); - } - } - enumerator->destroy(enumerator); -} - -/** - * list all OCSP responses - */ -static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out) -{ - bool first = TRUE, ok; - enumerator_t *enumerator = list->create_enumerator(list); - certificate_t *cert; - time_t produced, usable, now = time(NULL); - - while (enumerator->enumerate(enumerator, (void**)&cert)) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of OCSP responses:\n"); - fprintf(out, "\n"); - first = FALSE; - } - fprintf(out, " signer: \"%Y\"\n", cert->get_issuer(cert)); - - /* check validity */ - ok = cert->get_validity(cert, &now, &produced, &usable); - fprintf(out, " validity: produced at %T\n", &produced, utc); - fprintf(out, " usable till %T, ", &usable, utc); - if (ok) - { - fprintf(out, "ok\n"); - } - else - { - fprintf(out, "expired (%V ago)\n", &now, &usable); - } - } - enumerator->destroy(enumerator); + list->destroy_offset(list, offsetof(certificate_t, destroy)); } /** @@ -1439,19 +976,15 @@ METHOD(stroke_list_t, list, void, { linked_list_t *cert_list = NULL; + cert_printer = certificate_printer_create(out, TRUE, msg->list.utc); + if (msg->list.flags & LIST_PUBKEYS) { - linked_list_t *pubkey_list = create_unique_cert_list(CERT_TRUSTED_PUBKEY); - - stroke_list_pubkeys(pubkey_list, msg->list.utc, out); - pubkey_list->destroy_offset(pubkey_list, offsetof(certificate_t, destroy)); + stroke_list_other_certs(CERT_TRUSTED_PUBKEY); } if (msg->list.flags & LIST_CERTS) { - linked_list_t *pgp_list = create_unique_cert_list(CERT_GPG); - - stroke_list_pgp(pgp_list, msg->list.utc, out); - pgp_list->destroy_offset(pgp_list, offsetof(certificate_t, destroy)); + stroke_list_other_certs(CERT_GPG); } if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS)) { @@ -1459,47 +992,33 @@ METHOD(stroke_list_t, list, void, } if (msg->list.flags & LIST_CERTS) { - stroke_list_certs(cert_list, "X.509 End Entity Certificates", - X509_NONE, msg->list.utc, out); + stroke_list_x509_certs(cert_list, X509_NONE); } if (msg->list.flags & LIST_CACERTS) { - stroke_list_certs(cert_list, "X.509 CA Certificates", - X509_CA, msg->list.utc, out); + stroke_list_x509_certs(cert_list, X509_CA); } if (msg->list.flags & LIST_OCSPCERTS) { - stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates", - X509_OCSP_SIGNER, msg->list.utc, out); + stroke_list_x509_certs(cert_list, X509_OCSP_SIGNER); } if (msg->list.flags & LIST_AACERTS) { - stroke_list_certs(cert_list, "X.509 AA Certificates", - X509_AA, msg->list.utc, out); + stroke_list_x509_certs(cert_list, X509_AA); } DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy)); if (msg->list.flags & LIST_ACERTS) { - linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC); - - stroke_list_acerts(ac_list, msg->list.utc, out); - ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy)); + stroke_list_other_certs(CERT_X509_AC); } if (msg->list.flags & LIST_CRLS) { - linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL); - - stroke_list_crls(crl_list, msg->list.utc, out); - crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy)); + stroke_list_other_certs(CERT_X509_CRL); } if (msg->list.flags & LIST_OCSP) { - linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE); - - stroke_list_ocsp(ocsp_list, msg->list.utc, out); - - ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy)); + stroke_list_other_certs(CERT_X509_OCSP_RESPONSE); } if (msg->list.flags & LIST_ALGS) { @@ -1509,6 +1028,8 @@ METHOD(stroke_list_t, list, void, { list_plugins(out); } + cert_printer->destroy(cert_printer); + cert_printer = NULL; } /** diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 29563e32f..ee32dbca2 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -590,17 +590,10 @@ static void stroke_loglevel(private_stroke_socket_t *this, fprintf(out, "command not allowed!\n"); return; } - if (strcaseeq(msg->loglevel.type, "any")) + if (!enum_from_name(debug_names, msg->loglevel.type, &group)) { - group = DBG_ANY; - } - else - { - if (!enum_from_name(debug_names, msg->loglevel.type, &group)) - { - fprintf(out, "unknown type '%s'!\n", msg->loglevel.type); - return; - } + fprintf(out, "unknown type '%s'!\n", msg->loglevel.type); + return; } charon->set_level(charon, group, msg->loglevel.level); } diff --git a/src/libcharon/plugins/systime_fix/Makefile.am b/src/libcharon/plugins/systime_fix/Makefile.am index 40a346440..95a33230f 100644 --- a/src/libcharon/plugins/systime_fix/Makefile.am +++ b/src/libcharon/plugins/systime_fix/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon if MONOLITHIC diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in index be148b6c3..0daff4434 100644 --- a/src/libcharon/plugins/systime_fix/Makefile.in +++ b/src/libcharon/plugins/systime_fix/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-systime-fix.la diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am index 90fbf4651..dab98129d 100644 --- a/src/libcharon/plugins/tnc_ifmap/Makefile.am +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am @@ -1,7 +1,6 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/libtls \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in index 17cc341c5..f124a1b38 100644 --- a/src/libcharon/plugins/tnc_ifmap/Makefile.in +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in @@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -435,7 +437,6 @@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/libtls \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c index d2ba2e345..2bad4fab0 100644 --- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c @@ -18,7 +18,6 @@ #include "tnc_ifmap_renew_session_job.h" #include -#include #include #define IFMAP_RENEW_SESSION_INTERVAL 150 @@ -51,8 +50,8 @@ static bool publish_device_ip_addresses(private_tnc_ifmap_listener_t *this) host_t *host; bool success = TRUE; - enumerator = hydra->kernel_interface->create_address_enumerator( - hydra->kernel_interface, ADDR_TYPE_REGULAR); + enumerator = charon->kernel->create_address_enumerator(charon->kernel, + ADDR_TYPE_REGULAR); while (enumerator->enumerate(enumerator, &host)) { if (!this->ifmap->publish_device_ip(this->ifmap, host)) diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am index 3478c5b30..fcda7d76f 100644 --- a/src/libcharon/plugins/tnc_pdp/Makefile.am +++ b/src/libcharon/plugins/tnc_pdp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius \ -I$(top_srcdir)/src/libtncif \ diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in index ef05275b7..bfd8cf820 100644 --- a/src/libcharon/plugins/tnc_pdp/Makefile.in +++ b/src/libcharon/plugins/tnc_pdp/Makefile.in @@ -420,6 +420,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -435,7 +437,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libradius \ -I$(top_srcdir)/src/libtncif \ diff --git a/src/libcharon/plugins/uci/Makefile.am b/src/libcharon/plugins/uci/Makefile.am index 134ced0e3..296c8db04 100644 --- a/src/libcharon/plugins/uci/Makefile.am +++ b/src/libcharon/plugins/uci/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index 2c031383a..a1c64ca1b 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am index 38923e068..1244cb317 100644 --- a/src/libcharon/plugins/unity/Makefile.am +++ b/src/libcharon/plugins/unity/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in index 4f0a7e736..00bb1498c 100644 --- a/src/libcharon/plugins/unity/Makefile.in +++ b/src/libcharon/plugins/unity/Makefile.in @@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am index f03f4744c..f8738adee 100644 --- a/src/libcharon/plugins/updown/Makefile.am +++ b/src/libcharon/plugins/updown/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index 619d17a0e..863e14430 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon AM_CFLAGS = \ diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c index 96282bee0..e51caab10 100644 --- a/src/libcharon/plugins/updown/updown_listener.c +++ b/src/libcharon/plugins/updown/updown_listener.c @@ -1,7 +1,8 @@ /* * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2016 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -21,7 +22,6 @@ #include "updown_listener.h" #include -#include #include #include @@ -205,25 +205,47 @@ static void push_vip_env(private_updown_listener_t *this, ike_sa_t *ike_sa, enumerator->destroy(enumerator); } +#define PORT_BUF_LEN 12 + /** * Determine proper values for port env variable */ -static u_int16_t get_port(traffic_selector_t *me, - traffic_selector_t *other, bool local) +static char* get_port(traffic_selector_t *me, traffic_selector_t *other, + char *port_buf, bool local) { + uint16_t port, to, from; + switch (max(me->get_protocol(me), other->get_protocol(other))) { case IPPROTO_ICMP: case IPPROTO_ICMPV6: { - u_int16_t port = me->get_from_port(me); - - port = max(port, other->get_from_port(other)); - return local ? traffic_selector_icmp_type(port) - : traffic_selector_icmp_code(port); + port = max(me->get_from_port(me), other->get_from_port(other)); + snprintf(port_buf, PORT_BUF_LEN, "%u", + local ? traffic_selector_icmp_type(port) + : traffic_selector_icmp_code(port)); + return port_buf; } } - return local ? me->get_from_port(me) : other->get_from_port(other); + if (local) + { + from = me->get_from_port(me); + to = me->get_to_port(me); + } + else + { + from = other->get_from_port(other); + to = other->get_to_port(other); + } + if (from == to || (from == 0 && to == 65535)) + { + snprintf(port_buf, PORT_BUF_LEN, "%u", from); + } + else + { + snprintf(port_buf, PORT_BUF_LEN, "%u:%u", from, to); + } + return port_buf; } /** @@ -241,6 +263,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa, int out; FILE *shell; process_t *process; + char port_buf[PORT_BUF_LEN]; char *envp[128] = {}; me = ike_sa->get_my_host(ike_sa); @@ -265,8 +288,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa, config->get_name(config)); if (up) { - if (hydra->kernel_interface->get_interface(hydra->kernel_interface, - me, &iface)) + if (charon->kernel->get_interface(charon->kernel, me, &iface)) { cache_iface(this, child_sa->get_reqid(child_sa), iface); } @@ -289,25 +311,29 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa, ike_sa->get_unique_id(ike_sa)); push_env(envp, countof(envp), "PLUTO_ME=%H", me); push_env(envp, countof(envp), "PLUTO_MY_ID=%Y", ike_sa->get_my_id(ike_sa)); - if (my_ts->to_subnet(my_ts, &host, &mask)) + if (!my_ts->to_subnet(my_ts, &host, &mask)) { - push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask); - host->destroy(host); + DBG1(DBG_CHD, "updown approximates local TS %R " + "by next larger subnet", my_ts); } - push_env(envp, countof(envp), "PLUTO_MY_PORT=%u", - get_port(my_ts, other_ts, TRUE)); + push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask); + host->destroy(host); + push_env(envp, countof(envp), "PLUTO_MY_PORT=%s", + get_port(my_ts, other_ts, port_buf, TRUE)); push_env(envp, countof(envp), "PLUTO_MY_PROTOCOL=%u", my_ts->get_protocol(my_ts)); push_env(envp, countof(envp), "PLUTO_PEER=%H", other); push_env(envp, countof(envp), "PLUTO_PEER_ID=%Y", ike_sa->get_other_id(ike_sa)); - if (other_ts->to_subnet(other_ts, &host, &mask)) + if (!other_ts->to_subnet(other_ts, &host, &mask)) { - push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask); - host->destroy(host); + DBG1(DBG_CHD, "updown approximates remote TS %R " + "by next larger subnet", other_ts); } - push_env(envp, countof(envp), "PLUTO_PEER_PORT=%u", - get_port(my_ts, other_ts, FALSE)); + push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask); + host->destroy(host); + push_env(envp, countof(envp), "PLUTO_PEER_PORT=%s", + get_port(my_ts, other_ts, port_buf, FALSE)); push_env(envp, countof(envp), "PLUTO_PEER_PROTOCOL=%u", other_ts->get_protocol(other_ts)); if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) || diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am index c99d23e4e..ca9b49906 100644 --- a/src/libcharon/plugins/vici/Makefile.am +++ b/src/libcharon/plugins/vici/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libstrongswan/plugins/pubkey \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" @@ -18,6 +18,7 @@ libstrongswan_vici_la_SOURCES = \ vici_message.h vici_message.c \ vici_builder.h vici_builder.c \ vici_dispatcher.h vici_dispatcher.c \ + vici_cert_info.h vici_cert_info.c \ vici_query.h vici_query.c \ vici_control.h vici_control.c \ vici_config.h vici_config.c \ @@ -38,6 +39,7 @@ ipseclib_LTLIBRARIES = libvici.la libvici_la_SOURCES = \ vici_message.c vici_message.h \ vici_builder.c vici_builder.h \ + vici_cert_info.h vici_cert_info.c \ libvici.c libvici.h libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la @@ -79,3 +81,7 @@ endif if USE_PYTHON_EGGS SUBDIRS += python endif + +if USE_PERL_CPAN +SUBDIRS += perl +endif diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in index 1a7870ae9..86ed00792 100644 --- a/src/libcharon/plugins/vici/Makefile.in +++ b/src/libcharon/plugins/vici/Makefile.in @@ -82,6 +82,7 @@ TESTS = vici_tests$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) @USE_RUBY_GEMS_TRUE@am__append_1 = ruby @USE_PYTHON_EGGS_TRUE@am__append_2 = python +@USE_PERL_CPAN_TRUE@am__append_3 = perl subdir = src/libcharon/plugins/vici DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -134,9 +135,10 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES) $(noinst_LTLIBRARIES) \ $(plugin_LTLIBRARIES) libstrongswan_vici_la_LIBADD = am_libstrongswan_vici_la_OBJECTS = vici_socket.lo vici_message.lo \ - vici_builder.lo vici_dispatcher.lo vici_query.lo \ - vici_control.lo vici_config.lo vici_cred.lo vici_attribute.lo \ - vici_authority.lo vici_logger.lo vici_plugin.lo + vici_builder.lo vici_dispatcher.lo vici_cert_info.lo \ + vici_query.lo vici_control.lo vici_config.lo vici_cred.lo \ + vici_attribute.lo vici_authority.lo vici_logger.lo \ + vici_plugin.lo libstrongswan_vici_la_OBJECTS = $(am_libstrongswan_vici_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -150,7 +152,8 @@ libstrongswan_vici_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @MONOLITHIC_TRUE@am_libstrongswan_vici_la_rpath = libvici_la_DEPENDENCIES = \ $(top_builddir)/src/libstrongswan/libstrongswan.la -am_libvici_la_OBJECTS = vici_message.lo vici_builder.lo libvici.lo +am_libvici_la_OBJECTS = vici_message.lo vici_builder.lo \ + vici_cert_info.lo libvici.lo libvici_la_OBJECTS = $(am_libvici_la_OBJECTS) am__EXEEXT_1 = vici_tests$(EXEEXT) am__dirstamp = $(am__leading_dot)dirstamp @@ -270,7 +273,7 @@ am__tty_colors = { \ std=''; \ fi; \ } -DIST_SUBDIRS = ruby python +DIST_SUBDIRS = ruby python perl DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -509,6 +512,8 @@ strongswan_conf = @strongswan_conf@ strongswan_options = @strongswan_options@ swanctldir = @swanctldir@ sysconfdir = @sysconfdir@ +systemd_CFLAGS = @systemd_CFLAGS@ +systemd_LIBS = @systemd_LIBS@ systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ systemd_daemon_LIBS = @systemd_daemon_LIBS@ systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ @@ -524,7 +529,7 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libstrongswan/plugins/pubkey \ -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" @@ -538,6 +543,7 @@ libstrongswan_vici_la_SOURCES = \ vici_message.h vici_message.c \ vici_builder.h vici_builder.c \ vici_dispatcher.h vici_dispatcher.c \ + vici_cert_info.h vici_cert_info.c \ vici_query.h vici_query.c \ vici_control.h vici_control.c \ vici_config.h vici_config.c \ @@ -553,6 +559,7 @@ ipseclib_LTLIBRARIES = libvici.la libvici_la_SOURCES = \ vici_message.c vici_message.h \ vici_builder.c vici_builder.h \ + vici_cert_info.h vici_cert_info.c \ libvici.c libvici.h libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la @@ -578,7 +585,7 @@ vici_tests_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ $(top_builddir)/src/libstrongswan/tests/libtest.la -SUBDIRS = $(am__append_1) $(am__append_2) +SUBDIRS = $(am__append_1) $(am__append_2) $(am__append_3) all: all-recursive .SUFFIXES: @@ -739,6 +746,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_attribute.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_authority.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_builder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_cert_info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_control.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_cred.Plo@am__quote@ diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md index b9531d8a5..52929bd74 100644 --- a/src/libcharon/plugins/vici/README.md +++ b/src/libcharon/plugins/vici/README.md @@ -258,7 +258,8 @@ Initiates an SA while streaming _control-log_ events. { child = - timeout = + ike = + timeout = init-limits = loglevel = } => { @@ -266,6 +267,9 @@ Initiates an SA while streaming _control-log_ events. errmsg = } +The default timeout of 0 waits indefinitely for a result, and a timeout value +of -1 returns a result immediately. + ### terminate() ### Terminates an SA while streaming _control-log_ events. @@ -275,19 +279,40 @@ Terminates an SA while streaming _control-log_ events. ike = child_id = ike_id = - timeout = + timeout = loglevel = } => { success = errmsg = } +The default timeout of 0 waits indefinitely for a result, and a timeout value +of -1 returns a result immediately. + +### redirect() ### + +Redirect a client-initiated IKE_SA to another gateway. Only for IKEv2 and if +supported by the peer. + + { + ike = + ike-id = + peer-ip = + peer-id = + } => { + success = + errmsg = + } + ### install() ### Install a trap, drop or bypass policy defined by a CHILD_SA config. { child = + ike = } => { success = errmsg = @@ -361,7 +386,9 @@ call includes all certificates known by the daemon, not only those loaded over vici. { - type = + type = + flag = subject = } => { # completes after streaming list-cert events @@ -419,7 +446,8 @@ Unload a previously loaded connection definition by name. Load a certificate into the daemon. { - type = + type = + flag = data = } => { success = @@ -544,6 +572,16 @@ List the currently loaded pools. } } +### get-algorithms() ### + +List currently loaded algorithms and their implementation. + + {} => { + = { + = + } + } + ## Server-issued events ## Based on the packet layer, the vici plugin raises event messages using named @@ -588,8 +626,10 @@ command. version = state = local-host = + local-port = local-id = remote-host = + remote-port = remote-id = remote-xauth-id = remote-eap-id = @@ -735,9 +775,13 @@ The _list-cert_ event is issued to stream loaded certificates during an active _list-certs_ command. { - type = + type = + flag = has_privkey = data = + subject = + not-before =