aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Android.common.mk.in19
-rw-r--r--Android.mk (renamed from Android.mk.in)19
-rw-r--r--Doxyfile.in1
-rw-r--r--Makefile.am8
-rw-r--r--configure.in30
-rw-r--r--man/ipsec.conf.5.in3
-rw-r--r--man/strongswan.conf.5.in17
-rw-r--r--src/Makefile.am4
-rw-r--r--src/charon-nm/nm/nm_service.c3
-rw-r--r--src/charon/charon.c3
-rw-r--r--src/checksum/Makefile.am5
-rw-r--r--src/frontends/android/.classpath8
-rw-r--r--src/frontends/android/.gitignore4
-rw-r--r--src/frontends/android/AndroidManifest.xml29
-rw-r--r--src/frontends/android/README.ndk22
-rw-r--r--src/frontends/android/jni/.gitignore4
-rw-r--r--src/frontends/android/jni/Android.mk65
-rw-r--r--src/frontends/android/jni/libandroidbridge/Android.mk34
-rw-r--r--src/frontends/android/jni/libandroidbridge/charonservice.c124
-rw-r--r--src/frontends/android/jni/vstr/Android.mk11
-rw-r--r--src/frontends/android/proguard.cfg40
-rw-r--r--src/frontends/android/project.properties11
-rw-r--r--src/frontends/android/res/drawable-hdpi/ic_launcher.pngbin0 -> 4147 bytes
-rw-r--r--src/frontends/android/res/drawable-ldpi/ic_launcher.pngbin0 -> 1723 bytes
-rw-r--r--src/frontends/android/res/drawable-mdpi/ic_launcher.pngbin0 -> 2574 bytes
-rw-r--r--src/frontends/android/res/layout/main.xml12
-rw-r--r--src/frontends/android/res/values/strings.xml7
-rw-r--r--src/frontends/android/src/org/strongswan/android/CharonVpnService.java57
-rw-r--r--src/frontends/android/src/org/strongswan/android/strongSwanActivity.java40
-rw-r--r--src/libcharon/Android.mk5
-rw-r--r--src/libcharon/Makefile.am7
-rw-r--r--src/libcharon/daemon.h19
-rw-r--r--src/libcharon/network/packet.c19
-rw-r--r--src/libcharon/network/packet.h10
-rw-r--r--src/libcharon/network/receiver.c83
-rw-r--r--src/libcharon/network/receiver.h42
-rw-r--r--src/libcharon/network/sender.c26
-rw-r--r--src/libcharon/network/sender.h10
-rw-r--r--src/libcharon/network/socket.h10
-rw-r--r--src/libcharon/network/socket_manager.c16
-rw-r--r--src/libcharon/network/socket_manager.h10
-rw-r--r--src/libcharon/plugins/android/Makefile.am1
-rw-r--r--src/libcharon/plugins/android/android_plugin.c10
-rw-r--r--src/libcharon/plugins/android/android_service.c3
-rw-r--r--src/libcharon/plugins/android_log/Makefile.am17
-rw-r--r--src/libcharon/plugins/android_log/android_log_logger.c (renamed from src/libcharon/plugins/android/android_logger.c)24
-rw-r--r--src/libcharon/plugins/android_log/android_log_logger.h (renamed from src/libcharon/plugins/android/android_logger.h)18
-rw-r--r--src/libcharon/plugins/android_log/android_log_plugin.c76
-rw-r--r--src/libcharon/plugins/android_log/android_log_plugin.h42
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c3
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c9
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c3
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c4
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c2
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c199
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c62
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.c92
-rw-r--r--src/libcharon/plugins/sql/sql_config.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c6
-rw-r--r--src/libcharon/plugins/uci/uci_config.c4
-rw-r--r--src/libcharon/processing/jobs/migrate_job.c2
-rw-r--r--src/libcharon/sa/ike_sa.c13
-rw-r--r--src/libcharon/sa/ikev1/tasks/informational.c3
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c12
-rw-r--r--src/libhydra/kernel/kernel_interface.c13
-rw-r--r--src/libhydra/kernel/kernel_interface.h16
-rw-r--r--src/libhydra/kernel/kernel_ipsec.h13
-rw-r--r--src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c12
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c28
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c42
-rw-r--r--src/libipsec/Android.mk29
-rw-r--r--src/libipsec/Makefile.am20
-rw-r--r--src/libipsec/ipsec.c69
-rw-r--r--src/libipsec/ipsec.h56
-rw-r--r--src/libstrongswan/Android.mk2
-rw-r--r--src/libstrongswan/debug.c2
-rw-r--r--src/libstrongswan/debug.h2
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c21
-rw-r--r--src/libstrongswan/settings.c11
-rw-r--r--src/stroke/stroke.c2
82 files changed, 1458 insertions, 328 deletions
diff --git a/.gitignore b/.gitignore
index 34d3ee667..29adedde6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-/Android.mk
+/Android.common.mk
Makefile
Makefile.in
aclocal.m4
diff --git a/Android.common.mk.in b/Android.common.mk.in
new file mode 100644
index 000000000..1bc8a8304
--- /dev/null
+++ b/Android.common.mk.in
@@ -0,0 +1,19 @@
+# some common definitions used by the main and the NDK-specific Android.mk
+# include this after strongswan_PLUGINS has been defined
+
+# helper macros to only add source files for plugins included in the list above
+# source files are relative to the android.mk that called the macro
+plugin_enabled = $(filter $(1), $(strongswan_PLUGINS))
+add_plugin = $(if $(call plugin_enabled,$(1)), \
+ $(patsubst $(LOCAL_PATH)/%,%, \
+ $(wildcard \
+ $(subst %,$(subst -,_,$(strip $(1))), \
+ $(LOCAL_PATH)/plugins/%/%*.c \
+ ) \
+ ) \
+ ) \
+ )
+
+# strongSwan version, replaced by top Makefile
+strongswan_VERSION := "@PACKAGE_VERSION@"
+
diff --git a/Android.mk.in b/Android.mk
index a73981db0..edfdef397 100644
--- a/Android.mk.in
+++ b/Android.mk
@@ -16,8 +16,8 @@ include $(CLEAR_VARS)
# this is the list of plugins that are built into libstrongswan and charon
# also these plugins are loaded by default (if not changed in strongswan.conf)
-strongswan_CHARON_PLUGINS := openssl fips-prf random nonce pubkey pkcs1 \
- pem xcbc hmac kernel-netlink socket-default android \
+strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \
+ pkcs1 pem xcbc hmac kernel-netlink socket-default android \
stroke eap-identity eap-mschapv2 eap-md5
ifneq ($(strongswan_BUILD_SCEPCLIENT),)
@@ -32,27 +32,16 @@ strongswan_PLUGINS := $(sort $(strongswan_CHARON_PLUGINS) \
$(strongswan_STARTER_PLUGINS) \
$(strongswan_SCEPCLIENT_PLUGINS))
-# helper macros to only add source files for plugins included in the list above
-# source files are relative to the android.mk that called the macro
-plugin_enabled = $(findstring $(1), $(strongswan_PLUGINS))
-add_plugin = $(if $(call plugin_enabled,$(1)), \
- $(patsubst $(LOCAL_PATH)/%,%, \
- $(wildcard \
- $(subst %,$(subst -,_,$(strip $(1))), \
- $(LOCAL_PATH)/plugins/%/%*.c \
- ) \
- ) \
- ) \
- )
+include $(LOCAL_PATH)/Android.common.mk
# includes
strongswan_PATH := $(LOCAL_PATH)
libvstr_PATH := external/strongswan-support/vstr/include
libcurl_PATH := external/strongswan-support/libcurl/include
libgmp_PATH := external/strongswan-support/gmp
+openssl_PATH := external/openssl/include
# some definitions
-strongswan_VERSION := "@PACKAGE_VERSION@"
strongswan_DIR := "/system/bin"
strongswan_SBINDIR := "/system/bin"
strongswan_PIDDIR := "/data/misc/vpn"
diff --git a/Doxyfile.in b/Doxyfile.in
index 7fb516190..343f130b3 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -530,6 +530,7 @@ WARN_LOGFILE =
INPUT = @SRC_DIR@/src/libstrongswan \
@SRC_DIR@/src/libhydra \
@SRC_DIR@/src/libcharon \
+ @SRC_DIR@/src/libipsec \
@SRC_DIR@/src/libsimaka \
@SRC_DIR@/src/libtls \
@SRC_DIR@/src/libradius \
diff --git a/Makefile.am b/Makefile.am
index 908afca44..8a558c150 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,17 +6,17 @@ endif
ACLOCAL_AMFLAGS = -I m4/config
-EXTRA_DIST = Doxyfile.in LICENSE Android.mk.in Android.mk
+EXTRA_DIST = Doxyfile.in LICENSE Android.common.mk.in Android.common.mk Android.mk
CLEANFILES = Doxyfile
-BUILT_SOURCES = Android.mk
-MAINTAINERCLEANFILES = Android.mk
+BUILT_SOURCES = Android.common.mk
+MAINTAINERCLEANFILES = Android.common.mk
if USE_DEV_HEADERS
config_includedir = $(ipseclibdir)/include
nodist_config_include_HEADERS = config.h
endif
-Android.mk : Android.mk.in configure.in
+Android.common.mk : Android.common.mk.in configure.in
sed \
-e "s:\@PACKAGE_VERSION\@:$(PACKAGE_VERSION):" \
$(srcdir)/$@.in > $@
diff --git a/configure.in b/configure.in
index e3b7d43f8..918bb04b6 100644
--- a/configure.in
+++ b/configure.in
@@ -71,6 +71,29 @@ AC_ARG_WITH(
[AC_SUBST(ipsecgroup, "root")]
)
+AC_ARG_WITH(
+ [charon-udp-port],
+ AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500). Set to 0 to allocate randomly.]),
+ [AC_DEFINE_UNQUOTED(CHARON_UDP_PORT, [$withval], [UDP port used by charon locally])
+ AC_SUBST(charon_udp_port, [$withval])],
+ [AC_SUBST(charon_udp_port, 500)]
+)
+
+AC_ARG_WITH(
+ [charon-natt-port],
+ AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500). Set to 0 to allocate randomly.]),
+ [AC_DEFINE_UNQUOTED(CHARON_NATT_PORT, [$withval], [UDP post used by charon locally in case a NAT is detected])
+ AC_SUBST(charon_natt_port, [$withval])],
+ [AC_SUBST(charon_natt_port, 4500)]
+)
+
+AC_MSG_CHECKING([configured UDP ports ($charon_udp_port, $charon_natt_port)])
+if test x$charon_udp_port != x0 -a x$charon_udp_port = x$charon_natt_port; then
+ AC_MSG_ERROR(the ports have to be different)
+else
+ AC_MSG_RESULT(ok)
+fi
+
# convert script name to uppercase
AC_SUBST(ipsec_script_upper, [`echo -n "$ipsec_script" | tr a-z A-Z`])
@@ -152,6 +175,7 @@ ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.])
ARG_ENABL_SET([kernel-pfkey], [enable the PF_KEY kernel interface.])
ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.])
ARG_ENABL_SET([kernel-klips], [enable the KLIPS kernel interface.])
+ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.])
ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.])
ARG_ENABL_SET([socket-raw], [enable raw socket implementation of charon])
ARG_ENABL_SET([socket-dynamic], [enable dynamic socket implementation for charon])
@@ -184,6 +208,7 @@ ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.])
ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.])
ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.])
ARG_ENABL_SET([android], [enable Android specific plugin.])
+ARG_ENABL_SET([android-log], [enable Android specific logger plugin.])
ARG_ENABL_SET([maemo], [enable Maemo specific plugin.])
ARG_ENABL_SET([nm], [enable NetworkManager backend.])
ARG_ENABL_SET([ha], [enable high availability cluster plugin.])
@@ -914,6 +939,7 @@ ADD_PLUGIN([medsrv], [c charon])
ADD_PLUGIN([medcli], [c charon])
ADD_PLUGIN([dhcp], [c charon])
ADD_PLUGIN([android], [c charon])
+ADD_PLUGIN([android-log], [c charon])
ADD_PLUGIN([ha], [c charon])
ADD_PLUGIN([whitelist], [c charon])
ADD_PLUGIN([certexpire], [c charon])
@@ -995,6 +1021,7 @@ AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
AM_CONDITIONAL(USE_ANDROID, test x$android = xtrue)
+AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue)
AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue)
AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
AM_CONDITIONAL(USE_SQL, test x$sql = xtrue)
@@ -1081,6 +1108,7 @@ AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue)
+AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue)
@@ -1172,6 +1200,7 @@ AC_OUTPUT(
src/libhydra/plugins/kernel_pfkey/Makefile
src/libhydra/plugins/kernel_pfroute/Makefile
src/libhydra/plugins/resolve/Makefile
+ src/libipsec/Makefile
src/libsimaka/Makefile
src/libtls/Makefile
src/libradius/Makefile
@@ -1234,6 +1263,7 @@ AC_OUTPUT(
src/libcharon/plugins/coupling/Makefile
src/libcharon/plugins/radattr/Makefile
src/libcharon/plugins/android/Makefile
+ src/libcharon/plugins/android_log/Makefile
src/libcharon/plugins/maemo/Makefile
src/libcharon/plugins/stroke/Makefile
src/libcharon/plugins/updown/Makefile
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index 1f88761be..ca77ee7de 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -1051,7 +1051,8 @@ A comma separated list containing type/level-pairs may
be specified, e.g:
.B dmn 3, ike 1, net -1.
Acceptable values for types are
-.B dmn, mgr, ike, chd, job, cfg, knl, net, asn, enc, lib, tls, tnc, imc, imv, pts
+.B dmn, mgr, ike, chd, job, cfg, knl, net, asn, enc, lib, esp, tls,
+.B tnc, imc, imv, pts
and the level is one of
.B -1, 0, 1, 2, 3, 4
(for silent, audit, control, controlmore, raw, private). By default, the level
diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in
index fb9f1853d..4fba2344b 100644
--- a/man/strongswan.conf.5.in
+++ b/man/strongswan.conf.5.in
@@ -210,6 +210,15 @@ Enable multiple authentication exchanges (RFC 4739)
.BR charon.nbns2
WINS servers assigned to peer via configuration payload (CP)
.TP
+.BR charon.port " [500]"
+UDP port used locally. If set to 0 a random port will be allocated.
+.TP
+.BR charon.port_nat_t " [4500]"
+UDP port used locally in case of NAT-T. If set to 0 a random port will be
+allocated. Has to be different from
+.BR charon.port ,
+otherwise a random port will be allocated.
+.TP
.BR charon.process_route " [yes]"
Process RTM_NEWROUTE and RTM_DELROUTE events
.TP
@@ -272,7 +281,7 @@ Section to define syslog loggers, see LOGGER CONFIGURATION
Number of worker threads in charon
.SS charon.plugins subsection
.TP
-.BR charon.plugins.android.loglevel " [1]"
+.BR charon.plugins.android_log.loglevel " [1]"
Loglevel for logging to Android specific logger
.TP
.BR charon.plugins.attr
@@ -486,6 +495,9 @@ is appended to this prefix to make it unique. The result has to be a valid
interface name according to the rules defined by resolvconf. Also, it should
have a high priority according to the order defined in interface-order(5).
.TP
+.BR charon.plugins.socket-default.set_source " [yes]"
+Set source address on outbound packets, if possible.
+.TP
.BR charon.plugins.sql.database
Database URI for charons SQL plugin
.TP
@@ -922,6 +934,9 @@ Packet encoding/decoding encryption/decryption operations
.B tls
libtls library messages
.TP
+.B esp
+libipsec library messages
+.TP
.B lib
libstrongwan library messages
.TP
diff --git a/src/Makefile.am b/src/Makefile.am
index 452036b8b..e4c0374a2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,10 @@ if USE_LIBHYDRA
SUBDIRS += libhydra
endif
+if USE_LIBIPSEC
+ SUBDIRS += libipsec
+endif
+
if USE_SIMAKA
SUBDIRS += libsimaka
endif
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index 86d293d97..ccfa210a0 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -497,7 +497,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
/**
* Set up configurations
*/
- ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
(char*)address, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg,
diff --git a/src/charon/charon.c b/src/charon/charon.c
index be4a9548e..bd36c72f4 100644
--- a/src/charon/charon.c
+++ b/src/charon/charon.c
@@ -387,7 +387,7 @@ static void usage(const char *msg)
" [--version]\n"
" [--use-syslog]\n"
" [--debug-<type> <level>]\n"
- " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib)\n"
+ " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
" <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
" 2 = controlmore, 3 = raw, 4 = private)\n"
"\n"
@@ -466,6 +466,7 @@ int main(int argc, char *argv[])
{ "debug-imv", required_argument, &group, DBG_IMV },
{ "debug-pts", required_argument, &group, DBG_PTS },
{ "debug-tls", required_argument, &group, DBG_TLS },
+ { "debug-esp", required_argument, &group, DBG_ESP },
{ "debug-lib", required_argument, &group, DBG_LIB },
{ 0,0,0,0 }
};
diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am
index 0d0da5acf..1405fcd05 100644
--- a/src/checksum/Makefile.am
+++ b/src/checksum/Makefile.am
@@ -40,6 +40,11 @@ if !MONOLITHIC
endif
endif
+if USE_LIBIPSEC
+ deps += $(top_builddir)/src/libipsec/libipsec.la
+ libs += $(DESTDIR)$(ipseclibdir)/libipsec.so
+endif
+
if USE_TLS
deps += $(top_builddir)/src/libtls/libtls.la
libs += $(DESTDIR)$(ipseclibdir)/libtls.so
diff --git a/src/frontends/android/.classpath b/src/frontends/android/.classpath
new file mode 100644
index 000000000..3f9691c5d
--- /dev/null
+++ b/src/frontends/android/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/src/frontends/android/.gitignore b/src/frontends/android/.gitignore
new file mode 100644
index 000000000..a031dba58
--- /dev/null
+++ b/src/frontends/android/.gitignore
@@ -0,0 +1,4 @@
+bin/
+gen/
+libs/
+obj/
diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml
new file mode 100644
index 000000000..5b1d03d7c
--- /dev/null
+++ b/src/frontends/android/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.strongswan.android"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".strongSwanActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <service android:name=".CharonVpnService" android:permission="android.permission.BIND_VPN_SERVICE">
+ <intent-filter>
+ <action android:name="android.net.VpnService"/>
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/src/frontends/android/README.ndk b/src/frontends/android/README.ndk
new file mode 100644
index 000000000..e1dbac39c
--- /dev/null
+++ b/src/frontends/android/README.ndk
@@ -0,0 +1,22 @@
+To build this within the NDK several things have to be added in the jni
+folder:
+
+ - strongswan: The strongSwan sources. This can either be an extracted tarball,
+ or a symlink to the Git repository. To build from the repository the sources
+ have to be prepared first (see HACKING for a list of required tools):
+
+ ./autogen.sh && ./configure && make && make distclean
+
+ - openssl: The OpenSSL sources. Since the sources need to be changed to be
+ built on Android (and especially in the NDK), we provide a modified mirror
+ of the official Android OpenSSL version on git.strongswan.org.
+
+ - vstr: The Vstr string library. Since cross-compiling this library is not
+ that easy with the configure script and Makefiles included in the tarball,
+ the easiest way to build it is using either droid-gcc (as described on
+ wiki.strongswan.org) or a standalone toolchain built with the NDK.
+ The build script provided on the wiki builds the library with droid-gcc
+ and copies the required header files to the configured installation
+ directory. Please note that the Android.mk provided on the wiki (vstr.mk)
+ does not work in the NDK. A replacement is already in place in jni/vstr.
+
diff --git a/src/frontends/android/jni/.gitignore b/src/frontends/android/jni/.gitignore
new file mode 100644
index 000000000..90fd652f0
--- /dev/null
+++ b/src/frontends/android/jni/.gitignore
@@ -0,0 +1,4 @@
+openssl
+strongswan
+vstr/libvstr.a
+vstr/include
diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk
new file mode 100644
index 000000000..431415ae7
--- /dev/null
+++ b/src/frontends/android/jni/Android.mk
@@ -0,0 +1,65 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \
+ pkcs1 pem xcbc hmac socket-default \
+ eap-identity eap-mschapv2 eap-md5
+
+strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS)
+
+include $(LOCAL_PATH)/strongswan/Android.common.mk
+
+# includes
+strongswan_PATH := $(LOCAL_PATH)/strongswan
+libvstr_PATH := $(LOCAL_PATH)/vstr/include
+openssl_PATH := $(LOCAL_PATH)/openssl/include
+
+# CFLAGS (partially from a configure run using droid-gcc)
+strongswan_CFLAGS := \
+ -Wno-format \
+ -Wno-pointer-sign \
+ -Wno-pointer-arith \
+ -Wno-sign-compare \
+ -Wno-strict-aliasing \
+ -DHAVE___BOOL \
+ -DHAVE_STDBOOL_H \
+ -DHAVE_ALLOCA_H \
+ -DHAVE_ALLOCA \
+ -DHAVE_CLOCK_GETTIME \
+ -DHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC \
+ -DHAVE_PRCTL \
+ -DHAVE_LINUX_UDP_H \
+ -DHAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY \
+ -DHAVE_IPSEC_MODE_BEET \
+ -DHAVE_IPSEC_DIR_FWD \
+ -DOPENSSL_NO_EC \
+ -DOPENSSL_NO_ECDSA \
+ -DOPENSSL_NO_ECDH \
+ -DOPENSSL_NO_ENGINE \
+ -DCONFIG_H_INCLUDED \
+ -DCAPABILITIES \
+ -DCAPABILITIES_NATIVE \
+ -DMONOLITHIC \
+ -DUSE_IKEV1 \
+ -DUSE_IKEV2 \
+ -DUSE_VSTR \
+ -DDEBUG \
+ -DCHARON_UDP_PORT=0 \
+ -DCHARON_NATT_PORT=0 \
+ -DVERSION=\"$(strongswan_VERSION)\" \
+ -DDEV_RANDOM=\"/dev/random\" \
+ -DDEV_URANDOM=\"/dev/urandom\"
+
+# only for Android 2.0+
+strongswan_CFLAGS += \
+ -DHAVE_IN6ADDR_ANY
+
+include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
+ vstr \
+ openssl \
+ libandroidbridge \
+ strongswan/src/libipsec \
+ strongswan/src/libcharon \
+ strongswan/src/libhydra \
+ strongswan/src/libstrongswan \
+))
diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk
new file mode 100644
index 000000000..3b8b98b86
--- /dev/null
+++ b/src/frontends/android/jni/libandroidbridge/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+charonservice.c
+
+# build libandroidbridge -------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/libipsec \
+ $(strongswan_PATH)/src/libhydra \
+ $(strongswan_PATH)/src/libcharon \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
+ -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"'
+
+LOCAL_MODULE := libandroidbridge
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_LDLIBS := -llog
+
+LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libipsec libcharon
+
+include $(BUILD_SHARED_LIBRARY)
+
+
diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c
new file mode 100644
index 000000000..424d50d24
--- /dev/null
+++ b/src/frontends/android/jni/libandroidbridge/charonservice.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <android/log.h>
+#include <jni.h>
+
+#include <hydra.h>
+#include <ipsec.h>
+#include <daemon.h>
+#include <library.h>
+
+#define JNI_PACKAGE org_strongswan_android
+
+#define JNI_METHOD_PP(pack, klass, name, ret, ...) \
+ ret Java_##pack##_##klass##_##name(JNIEnv *env, jobject this, ##__VA_ARGS__)
+
+#define JNI_METHOD_P(pack, klass, name, ret, ...) \
+ JNI_METHOD_PP(pack, klass, name, ret, ##__VA_ARGS__)
+
+#define JNI_METHOD(klass, name, ret, ...) \
+ JNI_METHOD_P(JNI_PACKAGE, klass, name, ret, ##__VA_ARGS__)
+
+/**
+ * hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Logging hook for library logs, using android specific logging
+ */
+static void dbg_android(debug_t group, level_t level, char *fmt, ...)
+{
+ va_list args;
+
+ if (level <= 4)
+ {
+ char sgroup[16], buffer[8192];
+ char *current = buffer, *next;
+ snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+ while (current)
+ { /* log each line separately */
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n",
+ sgroup, current);
+ current = next;
+ }
+ }
+}
+
+/**
+ * Initialize charon and the libraries via JNI
+ */
+JNI_METHOD(CharonVpnService, initializeCharon, void)
+{
+ /* logging for library during initialization, as we have no bus yet */
+ dbg = dbg_android;
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ library_deinit();
+ return;
+ }
+
+ if (!libhydra_init("charon"))
+ {
+ libhydra_deinit();
+ library_deinit();
+ return;
+ }
+
+ if (!libipsec_init())
+ {
+ libipsec_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return;
+ }
+
+ if (!libcharon_init("charon") ||
+ !charon->initialize(charon, PLUGINS))
+ {
+ libcharon_deinit();
+ libipsec_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return;
+ }
+
+ /* start daemon (i.e. the threads in the thread-pool) */
+ charon->start(charon);
+}
+
+/**
+ * Initialize charon and the libraries via JNI
+ */
+JNI_METHOD(CharonVpnService, deinitializeCharon, void)
+{
+ libcharon_deinit();
+ libipsec_deinit();
+ libhydra_deinit();
+ library_deinit();
+}
+
diff --git a/src/frontends/android/jni/vstr/Android.mk b/src/frontends/android/jni/vstr/Android.mk
new file mode 100644
index 000000000..87355a671
--- /dev/null
+++ b/src/frontends/android/jni/vstr/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := libvstr.a
+
+LOCAL_MODULE := libvstr
+
+LOCAL_PRELINK_MODULE := false
+
+include $(PREBUILT_STATIC_LIBRARY)
diff --git a/src/frontends/android/proguard.cfg b/src/frontends/android/proguard.cfg
new file mode 100644
index 000000000..b1cdf17b5
--- /dev/null
+++ b/src/frontends/android/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/src/frontends/android/project.properties b/src/frontends/android/project.properties
new file mode 100644
index 000000000..730e911f2
--- /dev/null
+++ b/src/frontends/android/project.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-14
diff --git a/src/frontends/android/res/drawable-hdpi/ic_launcher.png b/src/frontends/android/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 000000000..8074c4c57
--- /dev/null
+++ b/src/frontends/android/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/src/frontends/android/res/drawable-ldpi/ic_launcher.png b/src/frontends/android/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 000000000..1095584ec
--- /dev/null
+++ b/src/frontends/android/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/src/frontends/android/res/drawable-mdpi/ic_launcher.png b/src/frontends/android/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 000000000..a07c69fa5
--- /dev/null
+++ b/src/frontends/android/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/src/frontends/android/res/layout/main.xml b/src/frontends/android/res/layout/main.xml
new file mode 100644
index 000000000..bc12cd823
--- /dev/null
+++ b/src/frontends/android/res/layout/main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml
new file mode 100644
index 000000000..f4df7613e
--- /dev/null
+++ b/src/frontends/android/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World, strongSwanActivity!</string>
+ <string name="app_name">strongSwan</string>
+
+</resources> \ No newline at end of file
diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java
new file mode 100644
index 000000000..d917d3eae
--- /dev/null
+++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java
@@ -0,0 +1,57 @@
+package org.strongswan.android;
+
+import android.content.Intent;
+import android.net.VpnService;
+
+public class CharonVpnService extends VpnService
+{
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId)
+ {
+ // called whenever the service is started with startService
+ // create our own thread because we are running in the calling processes
+ // main thread
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onCreate()
+ {
+ // onCreate is only called once
+ initializeCharon();
+ super.onCreate();
+ }
+
+ @Override
+ public void onDestroy()
+ {
+ // called once the service is to be destroyed
+ deinitializeCharon();
+ super.onDestroy();
+ }
+
+ /**
+ * Initialization of charon, provided by libandroidbridge.so
+ */
+ public native void initializeCharon();
+
+ /**
+ * Deinitialize charon, provided by libandroidbridge.so
+ */
+ public native void deinitializeCharon();
+
+ /*
+ * The libraries are extracted to /data/data/org.strongswan.android/...
+ * during installation.
+ */
+ static
+ {
+ System.loadLibrary("crypto");
+ System.loadLibrary("strongswan");
+ System.loadLibrary("hydra");
+ System.loadLibrary("charon");
+ System.loadLibrary("ipsec");
+ System.loadLibrary("androidbridge");
+ }
+}
diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java
new file mode 100644
index 000000000..fabf71897
--- /dev/null
+++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java
@@ -0,0 +1,40 @@
+package org.strongswan.android;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.VpnService;
+import android.os.Bundle;
+
+public class strongSwanActivity extends Activity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ startVpnService();
+ }
+
+ private void startVpnService()
+ {
+ Intent intent = VpnService.prepare(this);
+ if (intent != null)
+ {
+ startActivityForResult(intent, 0);
+ }
+ else
+ {
+ onActivityResult(0, RESULT_OK, null);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data)
+ {
+ if (resultCode == RESULT_OK)
+ {
+ Intent intent = new Intent(this, CharonVpnService.class);
+ startService(intent);
+ }
+ }
+}
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index db05d3db0..5e93e235f 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -130,6 +130,11 @@ LOCAL_C_INCLUDES += frameworks/base/cmds/keystore
LOCAL_SHARED_LIBRARIES += libcutils
endif
+LOCAL_SRC_FILES += $(call add_plugin, android-log)
+ifneq ($(call plugin_enabled, android-log),)
+LOCAL_LDLIBS += -llog
+endif
+
LOCAL_SRC_FILES += $(call add_plugin, attr)
LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index 2d4227990..fd910f73f 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -456,6 +456,13 @@ if MONOLITHIC
endif
endif
+if USE_ANDROID_LOG
+ SUBDIRS += plugins/android_log
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/android_log/libstrongswan-android-log.la
+endif
+endif
+
if USE_MAEMO
SUBDIRS += plugins/maemo
if MONOLITHIC
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index f42a9f078..b67de77b8 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -178,16 +178,31 @@ typedef struct daemon_t daemon_t;
#define DEFAULT_THREADS 16
/**
- * UDP Port on which the daemon will listen for incoming traffic.
+ * Primary UDP port used by IKE.
*/
#define IKEV2_UDP_PORT 500
/**
- * UDP Port to which the daemon will float to if NAT is detected.
+ * UDP port defined for use in case a NAT is detected.
*/
#define IKEV2_NATT_PORT 4500
/**
+ * UDP port on which the daemon will listen for incoming traffic (also used as
+ * source port for outgoing traffic).
+ */
+#ifndef CHARON_UDP_PORT
+#define CHARON_UDP_PORT IKEV2_UDP_PORT
+#endif
+
+/**
+ * UDP port used by the daemon in case a NAT is detected.
+ */
+#ifndef CHARON_NATT_PORT
+#define CHARON_NATT_PORT IKEV2_NATT_PORT
+#endif
+
+/**
* Main class of daemon, contains some globals.
*/
struct daemon_t {
diff --git a/src/libcharon/network/packet.c b/src/libcharon/network/packet.c
index 19db362f7..c817e00fb 100644
--- a/src/libcharon/network/packet.c
+++ b/src/libcharon/network/packet.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -42,6 +43,11 @@ struct private_packet_t {
* message data
*/
chunk_t data;
+
+ /**
+ * actual chunk returned from get_data, adjusted when skip_bytes is called
+ */
+ chunk_t adjusted_data;
};
METHOD(packet_t, set_source, void,
@@ -73,14 +79,20 @@ METHOD(packet_t, get_destination, host_t*,
METHOD(packet_t, get_data, chunk_t,
private_packet_t *this)
{
- return this->data;
+ return this->adjusted_data;
}
METHOD(packet_t, set_data, void,
private_packet_t *this, chunk_t data)
{
free(this->data.ptr);
- this->data = data;
+ this->adjusted_data = this->data = data;
+}
+
+METHOD(packet_t, skip_bytes, void,
+ private_packet_t *this, size_t bytes)
+{
+ this->adjusted_data = chunk_skip(this->adjusted_data, bytes);
}
METHOD(packet_t, destroy, void,
@@ -108,7 +120,7 @@ METHOD(packet_t, clone_, packet_t*,
}
if (this->data.ptr != NULL)
{
- other->set_data(other, chunk_clone(this->data));
+ other->set_data(other, chunk_clone(this->adjusted_data));
}
return other;
}
@@ -128,6 +140,7 @@ packet_t *packet_create(void)
.get_source = _get_source,
.set_destination = _set_destination,
.get_destination = _get_destination,
+ .skip_bytes = _skip_bytes,
.clone = _clone_,
.destroy = _destroy,
},
diff --git a/src/libcharon/network/packet.h b/src/libcharon/network/packet.h
index 18d82c6fc..c53364104 100644
--- a/src/libcharon/network/packet.h
+++ b/src/libcharon/network/packet.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -93,6 +94,15 @@ struct packet_t {
void (*set_data) (packet_t *packet, chunk_t data);
/**
+ * Increase the offset where the actual packet data starts.
+ *
+ * @note The offset is reset to 0 when set_data() is called.
+ *
+ * @param bytes the number of additional bytes to skip
+ */
+ void (*skip_bytes) (packet_t *packet, size_t bytes);
+
+ /**
* Clones a packet_t object.
*
* @param clone clone of the packet
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index dff76e245..3a52f8dc3 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -27,6 +27,7 @@
#include <processing/jobs/process_message_job.h>
#include <processing/jobs/callback_job.h>
#include <crypto/hashers/hasher.h>
+#include <threading/mutex.h>
/** lifetime of a cookie, in seconds */
#define COOKIE_LIFETIME 10
@@ -55,6 +56,19 @@ struct private_receiver_t {
receiver_t public;
/**
+ * Registered callback for ESP packets
+ */
+ struct {
+ receiver_esp_cb_t cb;
+ void *data;
+ } esp_cb;
+
+ /**
+ * Mutex for ESP callback
+ */
+ mutex_t *esp_cb_mutex;
+
+ /**
* current secret to use for cookie calculation
*/
char secret[SECRET_LENGTH];
@@ -400,8 +414,10 @@ static job_requeue_t receive_packets(private_receiver_t *this)
ike_sa_id_t *id;
packet_t *packet;
message_t *message;
+ host_t *src, *dst;
status_t status;
bool supported = TRUE;
+ chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
/* read in a packet */
status = charon->socket->receive(charon->socket, &packet);
@@ -415,6 +431,46 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_FAIR;
}
+ data = packet->get_data(packet);
+ if (data.len == 1 && data.ptr[0] == 0xFF)
+ { /* silently drop NAT-T keepalives */
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+ else if (data.len < marker.len)
+ { /* drop packets that are too small */
+ DBG3(DBG_NET, "received packet is too short (%d bytes)", data.len);
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ /* if neither source nor destination port is 500 we assume an IKE packet
+ * with Non-ESP marker or an ESP packet */
+ dst = packet->get_destination(packet);
+ src = packet->get_source(packet);
+ if (dst->get_port(dst) != IKEV2_UDP_PORT &&
+ src->get_port(src) != IKEV2_UDP_PORT)
+ {
+ if (memeq(data.ptr, marker.ptr, marker.len))
+ { /* remove Non-ESP marker */
+ packet->skip_bytes(packet, marker.len);
+ }
+ else
+ { /* this seems to be an ESP packet */
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ if (this->esp_cb.cb)
+ {
+ this->esp_cb.cb(this->esp_cb.data, packet);
+ }
+ else
+ {
+ packet->destroy(packet);
+ }
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+ return JOB_REQUEUE_DIRECT;
+ }
+ }
+
/* parse message header */
message = message_create_from_packet(packet);
if (message->parse_header(message) != SUCCESS)
@@ -513,11 +569,33 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_DIRECT;
}
+METHOD(receiver_t, add_esp_cb, void,
+ private_receiver_t *this, receiver_esp_cb_t callback, void *data)
+{
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ this->esp_cb.cb = callback;
+ this->esp_cb.data = data;
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+}
+
+METHOD(receiver_t, del_esp_cb, void,
+ private_receiver_t *this, receiver_esp_cb_t callback)
+{
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ if (this->esp_cb.cb == callback)
+ {
+ this->esp_cb.cb = NULL;
+ this->esp_cb.data = NULL;
+ }
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+}
+
METHOD(receiver_t, destroy, void,
private_receiver_t *this)
{
this->rng->destroy(this->rng);
this->hasher->destroy(this->hasher);
+ this->esp_cb_mutex->destroy(this->esp_cb_mutex);
free(this);
}
@@ -531,8 +609,11 @@ receiver_t *receiver_create()
INIT(this,
.public = {
+ .add_esp_cb = _add_esp_cb,
+ .del_esp_cb = _del_esp_cb,
.destroy = _destroy,
},
+ .esp_cb_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.secret_switch = now,
.secret_offset = random() % now,
);
diff --git a/src/libcharon/network/receiver.h b/src/libcharon/network/receiver.h
index 1d9d4871e..93b3d3c0c 100644
--- a/src/libcharon/network/receiver.h
+++ b/src/libcharon/network/receiver.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -25,15 +26,28 @@
typedef struct receiver_t receiver_t;
#include <library.h>
+#include <network/packet.h>
#include <utils/host.h>
/**
+ * Callback called for any received UDP encapsulated ESP packet.
+ *
+ * Implementation should be quick as the receiver doesn't receive any packets
+ * while calling this function.
+ *
+ * @param data data supplied during registration of the callback
+ * @param packet decapsulated ESP packet
+ */
+typedef void (*receiver_esp_cb_t)(void *data, packet_t *packet);
+
+/**
* Receives packets from the socket and adds them to the job queue.
*
- * The receiver starts a thread, which reads on the blocking socket. A received
- * packet is preparsed and a process_message_job is queued in the job queue.
+ * The receiver uses a callback job, which reads on the blocking socket.
+ * A received packet is preparsed and a process_message_job is queued in the
+ * job queue.
*
- * To endure DoS attacks, cookies are enabled when to many IKE_SAs are half
+ * To endure DoS attacks, cookies are enabled when too many IKE_SAs are half
* open. The calculation of cookies is slightly different from the proposed
* method in RFC4306. We do not include a nonce, because we think the advantage
* we gain does not justify the overhead to parse the whole message.
@@ -47,14 +61,32 @@ typedef struct receiver_t receiver_t;
* secret is stored to allow a clean migration between secret changes.
*
* Further, the number of half-initiated IKE_SAs is limited per peer. This
- * mades it impossible for a peer to flood the server with its real IP address.
+ * makes it impossible for a peer to flood the server with its real IP address.
*/
struct receiver_t {
/**
+ * Register a callback which is called for any incoming ESP packets.
+ *
+ * @note Only the last callback registered will receive any packets.
+ *
+ * @param callback callback to register
+ * @param data data provided to callback
+ */
+ void (*add_esp_cb)(receiver_t *this, receiver_esp_cb_t callback,
+ void *data);
+
+ /**
+ * Unregister a previously registered callback for ESP packets.
+ *
+ * @param callback previously registered callback
+ */
+ void (*del_esp_cb)(receiver_t *this, receiver_esp_cb_t callback);
+
+ /**
* Destroys a receiver_t object.
*/
- void (*destroy) (receiver_t *receiver);
+ void (*destroy)(receiver_t *this);
};
/**
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index 75635d2e3..a919a0263 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -79,7 +80,7 @@ struct private_sender_t {
bool send_delay_response;
};
-METHOD(sender_t, send_, void,
+METHOD(sender_t, send_no_marker, void,
private_sender_t *this, packet_t *packet)
{
host_t *src, *dst;
@@ -115,10 +116,30 @@ METHOD(sender_t, send_, void,
this->mutex->unlock(this->mutex);
}
+METHOD(sender_t, send_, void,
+ private_sender_t *this, packet_t *packet)
+{
+ host_t *src, *dst;
+
+ /* if neither source nor destination port is 500 we add a Non-ESP marker */
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ if (dst->get_port(dst) != IKEV2_UDP_PORT &&
+ src->get_port(src) != IKEV2_UDP_PORT)
+ {
+ chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
+
+ data = chunk_cat("cc", marker, packet->get_data(packet));
+ packet->set_data(packet, data);
+ }
+
+ send_no_marker(this, packet);
+}
+
/**
* Job callback function to send packets
*/
-static job_requeue_t send_packets(private_sender_t * this)
+static job_requeue_t send_packets(private_sender_t *this)
{
packet_t *packet;
bool oldstate;
@@ -176,6 +197,7 @@ sender_t * sender_create()
INIT(this,
.public = {
.send = _send_,
+ .send_no_marker = _send_no_marker,
.flush = _flush,
.destroy = _destroy,
},
diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h
index 6ee070435..c4f18d73b 100644
--- a/src/libcharon/network/sender.h
+++ b/src/libcharon/network/sender.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -28,7 +29,7 @@ typedef struct sender_t sender_t;
#include <network/packet.h>
/**
- * Thread responsible for sending packets over the socket.
+ * Callback job responsible for sending IKE packets over the socket.
*/
struct sender_t {
@@ -44,6 +45,13 @@ struct sender_t {
void (*send) (sender_t *this, packet_t *packet);
/**
+ * The same as send() but does not add Non-ESP markers automatically.
+ *
+ * @param packet packet to send
+ */
+ void (*send_no_marker) (sender_t *this, packet_t *packet);
+
+ /**
* Enforce a flush of the send queue.
*
* This function blocks until all queued packets have been sent.
diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h
index be875035b..4a4ef52e6 100644
--- a/src/libcharon/network/socket.h
+++ b/src/libcharon/network/socket.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -68,6 +68,14 @@ struct socket_t {
status_t (*send) (socket_t *this, packet_t *packet);
/**
+ * Get the port this socket is listening on.
+ *
+ * @param nat_t TRUE to get the port used to float in case of NAT-T
+ * @return the port
+ */
+ u_int16_t (*get_port) (socket_t *this, bool nat_t);
+
+ /**
* Destroy a socket implementation.
*/
void (*destroy) (socket_t *this);
diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c
index 72a454301..d2736de8e 100644
--- a/src/libcharon/network/socket_manager.c
+++ b/src/libcharon/network/socket_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -89,6 +89,19 @@ METHOD(socket_manager_t, sender, status_t,
return status;
}
+METHOD(socket_manager_t, get_port, u_int16_t,
+ private_socket_manager_t *this, bool nat_t)
+{
+ u_int16_t port = 0;
+ this->lock->read_lock(this->lock);
+ if (this->socket)
+ {
+ port = this->socket->get_port(this->socket, nat_t);
+ }
+ this->lock->unlock(this->lock);
+ return port;
+}
+
static void create_socket(private_socket_manager_t *this)
{
socket_constructor_t create;
@@ -153,6 +166,7 @@ socket_manager_t *socket_manager_create()
.public = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.add_socket = _add_socket,
.remove_socket = _remove_socket,
.destroy = _destroy,
diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h
index 94185d21c..1909d1f25 100644
--- a/src/libcharon/network/socket_manager.h
+++ b/src/libcharon/network/socket_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -53,6 +53,14 @@ struct socket_manager_t {
status_t (*send) (socket_manager_t *this, packet_t *packet);
/**
+ * Get the port the registered socket is listening on.
+ *
+ * @param nat_t TRUE to get the port used to float in case of NAT-T
+ * @return the port, or 0, if no socket is registered
+ */
+ u_int16_t (*get_port) (socket_manager_t *this, bool nat_t);
+
+ /**
* Register a socket constructor.
*
* @param create constructor for the socket
diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am
index b922ef4af..b10cd9527 100644
--- a/src/libcharon/plugins/android/Makefile.am
+++ b/src/libcharon/plugins/android/Makefile.am
@@ -14,7 +14,6 @@ libstrongswan_android_la_SOURCES = \
android_plugin.c android_plugin.h \
android_service.c android_service.h \
android_handler.c android_handler.h \
- android_logger.c android_logger.h \
android_creds.c android_creds.h
libstrongswan_android_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c
index bad8bc042..c0f58e9b4 100644
--- a/src/libcharon/plugins/android/android_plugin.c
+++ b/src/libcharon/plugins/android/android_plugin.c
@@ -15,7 +15,6 @@
*/
#include "android_plugin.h"
-#include "android_logger.h"
#include "android_handler.h"
#include "android_creds.h"
#include "android_service.h"
@@ -36,11 +35,6 @@ struct private_android_plugin_t {
android_plugin_t public;
/**
- * Android specific logger
- */
- android_logger_t *logger;
-
- /**
* Android specific DNS handler
*/
android_handler_t *handler;
@@ -68,10 +62,8 @@ METHOD(plugin_t, destroy, void,
hydra->attributes->remove_handler(hydra->attributes,
&this->handler->handler);
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
- charon->bus->remove_logger(charon->bus, &this->logger->logger);
this->creds->destroy(this->creds);
this->handler->destroy(this->handler);
- this->logger->destroy(this->logger);
DESTROY_IF(this->service);
free(this);
}
@@ -91,14 +83,12 @@ plugin_t *android_plugin_create()
.destroy = _destroy,
},
},
- .logger = android_logger_create(),
.creds = android_creds_create(),
);
this->service = android_service_create(this->creds);
this->handler = android_handler_create(this->service != NULL);
- charon->bus->add_logger(charon->bus, &this->logger->logger);
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index 6ca7407ca..f2d8ddce9 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -264,7 +264,8 @@ static job_requeue_t initiate(private_android_service_t *this)
this->creds->set_username_password(this->creds, user, password);
}
- ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
hostname, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
new file mode 100644
index 000000000..3c180f1db
--- /dev/null
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-android-log.la
+else
+plugin_LTLIBRARIES = libstrongswan-android-log.la
+endif
+
+libstrongswan_android_log_la_SOURCES = \
+ android_log_plugin.c android_log_plugin.h \
+ android_log_logger.c android_log_logger.h
+
+libstrongswan_android_log_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android_log/android_log_logger.c
index 0c5f609f7..48bcaa577 100644
--- a/src/libcharon/plugins/android/android_logger.c
+++ b/src/libcharon/plugins/android_log/android_log_logger.c
@@ -16,23 +16,23 @@
#include <string.h>
#include <android/log.h>
-#include "android_logger.h"
+#include "android_log_logger.h"
#include <library.h>
#include <daemon.h>
#include <threading/mutex.h>
-typedef struct private_android_logger_t private_android_logger_t;
+typedef struct private_android_log_logger_t private_android_log_logger_t;
/**
- * Private data of an android_logger_t object
+ * Private data of an android_log_logger_t object
*/
-struct private_android_logger_t {
+struct private_android_log_logger_t {
/**
* Public interface
*/
- android_logger_t public;
+ android_log_logger_t public;
/**
* logging level
@@ -46,7 +46,7 @@ struct private_android_logger_t {
};
METHOD(logger_t, log_, void,
- private_android_logger_t *this, debug_t group, level_t level,
+ private_android_log_logger_t *this, debug_t group, level_t level,
int thread, ike_sa_t* ike_sa, const char *message)
{
int prio = level > 1 ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO;
@@ -71,13 +71,13 @@ METHOD(logger_t, log_, void,
}
METHOD(logger_t, get_level, level_t,
- private_android_logger_t *this, debug_t group)
+ private_android_log_logger_t *this, debug_t group)
{
return this->level;
}
-METHOD(android_logger_t, destroy, void,
- private_android_logger_t *this)
+METHOD(android_log_logger_t, destroy, void,
+ private_android_log_logger_t *this)
{
this->mutex->destroy(this->mutex);
free(this);
@@ -86,9 +86,9 @@ METHOD(android_logger_t, destroy, void,
/**
* Described in header.
*/
-android_logger_t *android_logger_create()
+android_log_logger_t *android_log_logger_create()
{
- private_android_logger_t *this;
+ private_android_log_logger_t *this;
INIT(this,
.public = {
@@ -100,7 +100,7 @@ android_logger_t *android_logger_create()
},
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.level = lib->settings->get_int(lib->settings,
- "%s.plugins.android.loglevel", 1, charon->name),
+ "%s.plugins.android_log.loglevel", 1, charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/android/android_logger.h b/src/libcharon/plugins/android_log/android_log_logger.h
index 15abbb43f..ed271bf6c 100644
--- a/src/libcharon/plugins/android/android_logger.h
+++ b/src/libcharon/plugins/android_log/android_log_logger.h
@@ -14,21 +14,21 @@
*/
/**
- * @defgroup android_logger android_logger
- * @{ @ingroup android
+ * @defgroup android_log_logger android_log_logger
+ * @{ @ingroup android_log
*/
-#ifndef ANDROID_LOGGER_H_
-#define ANDROID_LOGGER_H_
+#ifndef ANDROID_LOG_LOGGER_H_
+#define ANDROID_LOG_LOGGER_H_
#include <bus/bus.h>
-typedef struct android_logger_t android_logger_t;
+typedef struct android_log_logger_t android_log_logger_t;
/**
* Android specific logger.
*/
-struct android_logger_t {
+struct android_log_logger_t {
/**
* Implements logger_t interface
@@ -38,7 +38,7 @@ struct android_logger_t {
/**
* Destroy the logger.
*/
- void (*destroy)(android_logger_t *this);
+ void (*destroy)(android_log_logger_t *this);
};
@@ -47,6 +47,6 @@ struct android_logger_t {
*
* @return logger instance
*/
-android_logger_t *android_logger_create();
+android_log_logger_t *android_log_logger_create();
-#endif /** ANDROID_LOGGER_H_ @}*/
+#endif /** ANDROID_LOG_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/android_log/android_log_plugin.c b/src/libcharon/plugins/android_log/android_log_plugin.c
new file mode 100644
index 000000000..6757c2210
--- /dev/null
+++ b/src/libcharon/plugins/android_log/android_log_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "android_log_plugin.h"
+#include "android_log_logger.h"
+
+#include <daemon.h>
+
+typedef struct private_android_log_plugin_t private_android_log_plugin_t;
+
+/**
+ * Private data of an android_log_plugin_t object.
+ */
+struct private_android_log_plugin_t {
+
+ /**
+ * Public android_log_plugin_t interface.
+ */
+ android_log_plugin_t public;
+
+ /**
+ * Android specific logger
+ */
+ android_log_logger_t *logger;
+
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_android_log_plugin_t *this)
+{
+ return "android-log";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_android_log_plugin_t *this)
+{
+ charon->bus->remove_logger(charon->bus, &this->logger->logger);
+ this->logger->destroy(this->logger);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *android_log_plugin_create()
+{
+ private_android_log_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .reload = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .logger = android_log_logger_create(),
+ );
+
+ charon->bus->add_logger(charon->bus, &this->logger->logger);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/android_log/android_log_plugin.h b/src/libcharon/plugins/android_log/android_log_plugin.h
new file mode 100644
index 000000000..32c4dc10b
--- /dev/null
+++ b/src/libcharon/plugins/android_log/android_log_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_log android_log
+ * @ingroup cplugins
+ *
+ * @defgroup android_log_plugin android_log_plugin
+ * @{ @ingroup android_log
+ */
+
+#ifndef ANDROID_LOG_PLUGIN_H_
+#define ANDROID_LOG_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct android_log_plugin_t android_log_plugin_t;
+
+/**
+ * Plugin providing an Android specific logger implementation.
+ */
+struct android_log_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** ANDROID_LOG_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index d1edb3e55..ad458caad 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -203,7 +203,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
lib->credmgr->add_set(lib->credmgr, &this->creds.public);
/* create config and backend */
- ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, IKEV2_UDP_PORT,
+ ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
remote, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index d041d4cdc..f5da8b892 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -257,7 +257,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
else
{
ike_cfg = ike_cfg_create(FALSE, FALSE,
- this->local, FALSE, IKEV2_UDP_PORT,
+ this->local, FALSE, charon->socket->get_port(charon->socket, FALSE),
this->remote, FALSE, IKEV2_UDP_PORT);
}
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 440197260..ded6b2d20 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -108,12 +108,6 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
-METHOD(kernel_ipsec_t, bypass_socket, bool,
- private_load_tester_ipsec_t *this, int fd, int family)
-{
- return TRUE;
-}
-
METHOD(kernel_ipsec_t, destroy, void,
private_load_tester_ipsec_t *this)
{
@@ -141,7 +135,8 @@ load_tester_ipsec_t *load_tester_ipsec_create()
.query_policy = _query_policy,
.del_policy = _del_policy,
.flush_policies = (void*)return_failed,
- .bypass_socket = _bypass_socket,
+ .bypass_socket = (void*)return_true,
+ .enable_udp_decap = (void*)return_true,
.destroy = _destroy,
},
},
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index b5f50f1c6..f638a81b7 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -323,7 +323,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
NULL);
}
- ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
hostname, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 15d4ffa3f..829c8f05e 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -119,7 +119,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
return NULL;
}
ike_cfg = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
address, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
med_cfg = peer_cfg_create(
@@ -396,7 +396,7 @@ medcli_config_t *medcli_config_create(database_t *db)
.rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200),
.dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300),
.ike = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
"0.0.0.0", FALSE, IKEV2_UDP_PORT),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index ef3b04497..ebc142de2 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -141,7 +141,7 @@ medsrv_config_t *medsrv_config_create(database_t *db)
.rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200),
.dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300),
.ike = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", FALSE, IKEV2_UDP_PORT,
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
"0.0.0.0", FALSE, IKEV2_UDP_PORT),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index d1c5626b7..c2b073418 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -40,9 +40,6 @@
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <net/if.h>
-#ifdef __APPLE__
-#include <sys/sysctl.h>
-#endif
#include <hydra.h>
#include <daemon.h>
@@ -51,18 +48,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
-/* length of non-esp marker */
-#define MARKER_LEN sizeof(u_int32_t)
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -70,9 +55,6 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -101,22 +83,32 @@ struct private_socket_default_socket_t {
socket_default_socket_t public;
/**
- * IPv4 socket (500)
+ * Configured port (or random, if initially 0)
+ */
+ u_int16_t port;
+
+ /**
+ * Configured port for NAT-T (or random, if initially 0)
+ */
+ u_int16_t natt;
+
+ /**
+ * IPv4 socket (500 or port)
*/
int ipv4;
/**
- * IPv4 socket for NATT (4500)
+ * IPv4 socket for NAT-T (4500 or natt)
*/
int ipv4_natt;
/**
- * IPv6 socket (500)
+ * IPv6 socket (500 or port)
*/
int ipv6;
/**
- * IPv6 socket for NATT (4500)
+ * IPv6 socket for NAT-T (4500 or natt)
*/
int ipv6_natt;
@@ -124,6 +116,11 @@ struct private_socket_default_socket_t {
* Maximum packet size to receive
*/
int max_packet;
+
+ /**
+ * TRUE if the source address should be set on outbound packets
+ */
+ bool set_source;
};
METHOD(socket_t, receiver, status_t,
@@ -133,7 +130,7 @@ METHOD(socket_t, receiver, status_t,
chunk_t data;
packet_t *pkt;
host_t *source = NULL, *dest = NULL;
- int bytes_read = 0, data_offset;
+ int bytes_read = 0;
bool oldstate;
fd_set rfds;
@@ -171,22 +168,22 @@ METHOD(socket_t, receiver, status_t,
if (FD_ISSET(this->ipv4, &rfds))
{
- port = IKEV2_UDP_PORT;
+ port = this->port;
selected = this->ipv4;
}
if (FD_ISSET(this->ipv4_natt, &rfds))
{
- port = IKEV2_NATT_PORT;
+ port = this->natt;
selected = this->ipv4_natt;
}
if (FD_ISSET(this->ipv6, &rfds))
{
- port = IKEV2_UDP_PORT;
+ port = this->port;
selected = this->ipv6;
}
if (FD_ISSET(this->ipv6_natt, &rfds))
{
- port = IKEV2_NATT_PORT;
+ port = this->natt;
selected = this->ipv6_natt;
}
if (selected)
@@ -222,13 +219,6 @@ METHOD(socket_t, receiver, status_t,
}
DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
- if (bytes_read < MARKER_LEN)
- {
- DBG3(DBG_NET, "received packet too short (%d bytes)",
- bytes_read);
- return FAILED;
- }
-
/* read ancillary data to get destination address */
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
@@ -297,17 +287,8 @@ METHOD(socket_t, receiver, status_t,
pkt->set_source(pkt, source);
pkt->set_destination(pkt, dest);
DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
- data_offset = 0;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
- data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
+ data = chunk_create(buffer, bytes_read);
+ pkt->set_data(pkt, chunk_clone(data));
}
else
{
@@ -324,7 +305,7 @@ METHOD(socket_t, sender, status_t,
{
int sport, skt, family;
ssize_t bytes_sent;
- chunk_t data, marked;
+ chunk_t data;
host_t *src, *dst;
struct msghdr msg;
struct cmsghdr *cmsg;
@@ -339,7 +320,7 @@ METHOD(socket_t, sender, status_t,
/* send data */
sport = src->get_port(src);
family = dst->get_family(dst);
- if (sport == IKEV2_UDP_PORT)
+ if (sport == 0 || sport == this->port)
{
if (family == AF_INET)
{
@@ -350,7 +331,7 @@ METHOD(socket_t, sender, status_t,
skt = this->ipv6;
}
}
- else if (sport == IKEV2_NATT_PORT)
+ else if (sport == this->natt)
{
if (family == AF_INET)
{
@@ -360,17 +341,6 @@ METHOD(socket_t, sender, status_t,
{
skt = this->ipv6_natt;
}
- /* NAT keepalives without marker */
- if (data.len != 1 || data.ptr[0] != 0xFF)
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
}
else
{
@@ -387,7 +357,7 @@ METHOD(socket_t, sender, status_t,
msg.msg_iovlen = 1;
msg.msg_flags = 0;
- if (!src->is_anyaddr(src))
+ if (this->set_source && !src->is_anyaddr(src))
{
if (family == AF_INET)
{
@@ -450,11 +420,17 @@ METHOD(socket_t, sender, status_t,
return SUCCESS;
}
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_default_socket_t *this, bool nat_t)
+{
+ return nat_t ? this->natt : this->port;
+}
+
/**
* open a socket to send and receive packets
*/
static int open_socket(private_socket_default_socket_t *this,
- int family, u_int16_t port)
+ int family, u_int16_t *port)
{
int on = TRUE;
struct sockaddr_storage addr;
@@ -471,7 +447,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
- htoun16(&sin->sin_port, port);
+ htoun16(&sin->sin_port, *port);
addrlen = sizeof(struct sockaddr_in);
sol = SOL_IP;
#ifdef IP_PKTINFO
@@ -485,7 +461,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
- htoun16(&sin6->sin6_port, port);
+ htoun16(&sin6->sin6_port, *port);
addrlen = sizeof(struct sockaddr_in6);
sol = SOL_IPV6;
pktinfo = IPV6_RECVPKTINFO;
@@ -516,6 +492,32 @@ static int open_socket(private_socket_default_socket_t *this,
return 0;
}
+ /* retrieve randomly allocated port if needed */
+ if (*port == 0)
+ {
+ if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ *port = untoh16(&sin->sin_port);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ *port = untoh16(&sin6->sin6_port);
+ break;
+ }
+ }
+ }
+
/* get additional packet info on receive */
if (pktinfo > 0)
{
@@ -532,18 +534,6 @@ static int open_socket(private_socket_default_socket_t *this,
{
DBG1(DBG_NET, "installing IKE bypass policy failed");
}
-
-#ifndef __APPLE__
- {
- /* enable UDP decapsulation globally, only for one socket needed */
- int type = UDP_ENCAP_ESPINUDP;
- if (family == AF_INET && port == IKEV2_NATT_PORT &&
- setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
- {
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
- }
- }
-#endif
return skt;
}
@@ -581,50 +571,55 @@ socket_default_socket_t *socket_default_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.destroy = _destroy,
},
},
+ .port = lib->settings->get_int(lib->settings,
+ "%s.port", CHARON_UDP_PORT, charon->name),
+ .natt = lib->settings->get_int(lib->settings,
+ "%s.port_nat_t", CHARON_NATT_PORT, charon->name),
.max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, charon->name),
+ "%s.max_packet", MAX_PACKET, charon->name),
+ .set_source = lib->settings->get_bool(lib->settings,
+ "%s.plugins.socket-default.set_source", TRUE,
+ charon->name),
);
-#ifdef __APPLE__
+ if (this->port && this->port == this->natt)
{
- int natt_port = IKEV2_NATT_PORT;
- if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port,
- sizeof(natt_port)) != 0)
- {
- DBG1(DBG_NET, "could not set net.inet.ipsec.esp_port to %d: %s",
- natt_port, strerror(errno));
- }
+ DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
+ "port randomly");
+ this->natt = 0;
}
-#endif
- this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
- if (this->ipv4 == 0)
+ /* we allocate IPv6 sockets first as that will reserve randomly allocated
+ * ports also for IPv4 */
+ this->ipv6 = open_socket(this, AF_INET6, &this->port);
+ if (this->ipv6 == 0)
{
- DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
+ DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
}
else
{
- this->ipv4_natt = open_socket(this, AF_INET, IKEV2_NATT_PORT);
- if (this->ipv4_natt == 0)
+ this->ipv6_natt = open_socket(this, AF_INET6, &this->natt);
+ if (this->ipv6_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
}
}
- this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT);
- if (this->ipv6 == 0)
+ this->ipv4 = open_socket(this, AF_INET, &this->port);
+ if (this->ipv4 == 0)
{
- DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
+ DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
}
else
{
- this->ipv6_natt = open_socket(this, AF_INET6, IKEV2_NATT_PORT);
- if (this->ipv6_natt == 0)
+ this->ipv4_natt = open_socket(this, AF_INET, &this->natt);
+ if (this->ipv4_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
}
}
@@ -634,6 +629,14 @@ socket_default_socket_t *socket_default_socket_create()
destroy(this);
return NULL;
}
+
+ /* enable UDP decapsulation globally, only for one socket needed */
+ if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ this->ipv6_natt ?: this->ipv4_natt,
+ this->ipv6_natt ? AF_INET6 : AF_INET, this->natt))
+ {
+ DBG1(DBG_NET, "enabling UDP decapsulation failed");
+ }
return &this->public;
}
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index d4a9552f6..e0e0af6b6 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -45,18 +45,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
-/* length of non-esp marker */
-#define MARKER_LEN sizeof(u_int32_t)
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -64,9 +52,6 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -237,12 +222,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
}
DBG3(DBG_NET, "received packet %b", buffer, (u_int)len);
- if (len < MARKER_LEN)
- {
- DBG3(DBG_NET, "received packet too short (%d bytes)", len);
- return NULL;
- }
-
/* read ancillary data to get destination address */
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
@@ -297,12 +276,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
packet = packet_create();
packet->set_source(packet, source);
packet->set_destination(packet, dest);
- /* we assume a non-ESP marker if none of the ports is on 500 */
- if (dest->get_port(dest) != IKEV2_UDP_PORT &&
- source->get_port(source) != IKEV2_UDP_PORT)
- {
- data = chunk_skip(data, MARKER_LEN);
- }
packet->set_data(packet, chunk_clone(data));
return packet;
}
@@ -358,7 +331,7 @@ METHOD(socket_t, receiver, status_t,
static int open_socket(private_socket_dynamic_socket_t *this,
int family, u_int16_t port)
{
- int on = TRUE, type = UDP_ENCAP_ESPINUDP;
+ int on = TRUE;
struct sockaddr_storage addr;
socklen_t addrlen;
u_int sol, pktinfo = 0;
@@ -430,10 +403,12 @@ static int open_socket(private_socket_dynamic_socket_t *this,
}
/* enable UDP decapsulation on each socket */
- if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ fd, family, port))
{
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
+ DBG1(DBG_NET, "enabling UDP decapsulation failed");
}
+
return fd;
}
@@ -483,7 +458,7 @@ METHOD(socket_t, sender, status_t,
host_t *src, *dst;
int port, family;
ssize_t len;
- chunk_t data, marked;
+ chunk_t data;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
@@ -492,6 +467,7 @@ METHOD(socket_t, sender, status_t,
dst = packet->get_destination(packet);
family = src->get_family(src);
port = src->get_port(src);
+ port = port ?: CHARON_UDP_PORT;
skt = find_socket(this, family, port);
if (!skt)
{
@@ -501,19 +477,6 @@ METHOD(socket_t, sender, status_t,
data = packet->get_data(packet);
DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
- /* use non-ESP marker if none of the ports is 500, not for keep alives */
- if (port != IKEV2_UDP_PORT && dst->get_port(dst) != IKEV2_UDP_PORT &&
- !(data.len == 1 && data.ptr[0] == 0xFF))
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
-
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = dst->get_sockaddr(dst);;
msg.msg_namelen = *dst->get_sockaddr_len(dst);
@@ -572,6 +535,14 @@ METHOD(socket_t, sender, status_t,
return SUCCESS;
}
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_dynamic_socket_t *this, bool nat_t)
+{
+ /* we return 0 here for users that have no explicit port configured, the
+ * sender will default to the default port in this case */
+ return 0;
+}
+
METHOD(socket_t, destroy, void,
private_socket_dynamic_socket_t *this)
{
@@ -605,6 +576,7 @@ socket_dynamic_socket_t *socket_dynamic_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.destroy = _destroy,
},
},
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
index 6557fc12f..1b3c9e126 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c
+++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -55,15 +55,6 @@
#define IKE_VERSION_OFFSET 17
#define IKE_LENGTH_OFFSET 24
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
/* needed for older kernel headers */
#ifndef IPV6_2292PKTINFO
#define IPV6_2292PKTINFO 2
@@ -181,7 +172,7 @@ METHOD(socket_t, receiver, status_t,
DBG3(DBG_NET, "received IPv4 packet %b", buffer, bytes_read);
/* read source/dest from raw IP/UDP header */
- if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
+ if (bytes_read < IP_LEN + UDP_LEN)
{
DBG1(DBG_NET, "received IPv4 packet too short (%d bytes)",
bytes_read);
@@ -203,16 +194,9 @@ METHOD(socket_t, receiver, status_t,
pkt->set_destination(pkt, dest);
DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
data_offset = IP_LEN + UDP_LEN;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
+ data.ptr = buffer + data_offset;
+ pkt->set_data(pkt, chunk_clone(data));
}
else if (this->recv6 && FD_ISSET(this->recv6, &rfds))
{
@@ -242,7 +226,7 @@ METHOD(socket_t, receiver, status_t,
}
DBG3(DBG_NET, "received IPv6 packet %b", buffer, bytes_read);
- if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
+ if (bytes_read < IP_LEN + UDP_LEN)
{
DBG3(DBG_NET, "received IPv6 packet too short (%d bytes)",
bytes_read);
@@ -290,16 +274,9 @@ METHOD(socket_t, receiver, status_t,
pkt->set_destination(pkt, dest);
DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
data_offset = UDP_LEN;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
+ data.ptr = buffer + data_offset;
+ pkt->set_data(pkt, chunk_clone(data));
}
else
{
@@ -317,7 +294,7 @@ METHOD(socket_t, sender, status_t,
{
int sport, skt, family;
ssize_t bytes_sent;
- chunk_t data, marked;
+ chunk_t data;
host_t *src, *dst;
struct msghdr msg;
struct cmsghdr *cmsg;
@@ -332,7 +309,7 @@ METHOD(socket_t, sender, status_t,
/* send data */
sport = src->get_port(src);
family = dst->get_family(dst);
- if (sport == IKEV2_UDP_PORT)
+ if (sport == 0 || sport == CHARON_UDP_PORT)
{
if (family == AF_INET)
{
@@ -343,7 +320,7 @@ METHOD(socket_t, sender, status_t,
skt = this->send6;
}
}
- else if (sport == IKEV2_NATT_PORT)
+ else if (sport == CHARON_NATT_PORT)
{
if (family == AF_INET)
{
@@ -353,17 +330,6 @@ METHOD(socket_t, sender, status_t,
{
skt = this->send6_natt;
}
- /* NAT keepalives without marker */
- if (data.len != 1 || data.ptr[0] != 0xFF)
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
}
else
{
@@ -437,7 +403,6 @@ static int open_send_socket(private_socket_raw_socket_t *this,
int family, u_int16_t port)
{
int on = TRUE;
- int type = UDP_ENCAP_ESPINUDP;
struct sockaddr_storage addr;
int skt;
@@ -488,25 +453,29 @@ static int open_send_socket(private_socket_raw_socket_t *this,
return 0;
}
- if (family == AF_INET)
- {
- /* enable UDP decapsulation globally, only for one socket needed */
- if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
- {
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s; NAT-T may fail",
- strerror(errno));
- }
- }
-
if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
skt, family))
{
DBG1(DBG_NET, "installing bypass policy on send socket failed");
}
+ /* enable UDP decapsulation globally, only for one socket needed */
+ if (family == AF_INET && port == CHARON_NATT_PORT &&
+ !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ skt, family, port))
+ {
+ DBG1(DBG_NET, "enabling UDP decapsulation failed");
+ }
+
return skt;
}
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_raw_socket_t *this, bool nat_t)
+{
+ return nat_t ? CHARON_NATT_PORT : CHARON_UDP_PORT;
+}
+
/**
* open a socket to receive packets
*/
@@ -541,8 +510,8 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family)
{
/* Destination Port must be either port or natt_port */
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 6, 14),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, CHARON_UDP_PORT, 1, 0),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, CHARON_NATT_PORT, 6, 14),
/* port */
/* IKE version must be 2.x */
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET),
@@ -653,6 +622,7 @@ socket_raw_socket_t *socket_raw_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.destroy = _destroy,
},
},
@@ -667,7 +637,7 @@ socket_raw_socket_t *socket_raw_socket_create()
}
else
{
- this->send4 = open_send_socket(this, AF_INET, IKEV2_UDP_PORT);
+ this->send4 = open_send_socket(this, AF_INET, CHARON_UDP_PORT);
if (this->send4 == 0)
{
DBG1(DBG_NET, "could not open IPv4 send socket, IPv4 disabled");
@@ -675,7 +645,7 @@ socket_raw_socket_t *socket_raw_socket_create()
}
else
{
- this->send4_natt = open_send_socket(this, AF_INET, IKEV2_NATT_PORT);
+ this->send4_natt = open_send_socket(this, AF_INET, CHARON_NATT_PORT);
if (this->send4_natt == 0)
{
DBG1(DBG_NET, "could not open IPv4 NAT-T send socket");
@@ -690,7 +660,7 @@ socket_raw_socket_t *socket_raw_socket_create()
}
else
{
- this->send6 = open_send_socket(this, AF_INET6, IKEV2_UDP_PORT);
+ this->send6 = open_send_socket(this, AF_INET6, CHARON_UDP_PORT);
if (this->send6 == 0)
{
DBG1(DBG_NET, "could not open IPv6 send socket, IPv6 disabled");
@@ -698,7 +668,7 @@ socket_raw_socket_t *socket_raw_socket_create()
}
else
{
- this->send6_natt = open_send_socket(this, AF_INET6, IKEV2_NATT_PORT);
+ this->send6_natt = open_send_socket(this, AF_INET6, CHARON_NATT_PORT);
if (this->send6_natt == 0)
{
DBG1(DBG_NET, "could not open IPv6 NAT-T send socket");
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index dd9a0b09d..890077157 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -259,7 +259,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
ike_cfg_t *ike_cfg;
ike_cfg = ike_cfg_create(certreq, force_encap,
- local, FALSE, IKEV2_UDP_PORT,
+ local, FALSE, charon->socket->get_port(charon->socket, FALSE),
remote, FALSE, IKEV2_UDP_PORT);
add_ike_proposals(this, ike_cfg, id);
return ike_cfg;
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index c884da05d..bf93f2c34 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -188,6 +188,7 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
ike_cfg_t *ike_cfg;
char *interface;
host_t *host;
+ u_int16_t ikeport;
host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
if (host)
@@ -224,11 +225,14 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
}
}
}
+ ikeport = msg->add_conn.me.ikeport;
+ ikeport = (ikeport == IKEV2_UDP_PORT) ?
+ charon->socket->get_port(charon->socket, FALSE) : ikeport;
ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
msg->add_conn.force_encap,
msg->add_conn.me.address,
msg->add_conn.me.allow_any,
- msg->add_conn.me.ikeport,
+ ikeport,
msg->add_conn.other.address,
msg->add_conn.other.allow_any,
msg->add_conn.other.ikeport);
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 9b0fd73ad..5b698b8b2 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -169,7 +169,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
{
DESTROY_IF(this->peer_cfg);
ike_cfg = ike_cfg_create(FALSE, FALSE,
- local_addr, FALSE, IKEV2_UDP_PORT,
+ local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE),
remote_addr, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create(
@@ -267,7 +267,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool,
{
DESTROY_IF(this->ike_cfg);
this->ike_cfg = ike_cfg_create(FALSE, FALSE,
- local_addr, FALSE, IKEV2_UDP_PORT,
+ local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE),
remote_addr, FALSE, IKEV2_UDP_PORT);
this->ike_cfg->add_proposal(this->ike_cfg,
create_proposal(ike_proposal, PROTO_IKE));
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
index 45bac7cf8..57f344980 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -97,7 +97,7 @@ METHOD(job_t, execute, job_requeue_t,
ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
host = this->local->clone(this->local);
- host->set_port(host, IKEV2_UDP_PORT);
+ host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
ike_sa->set_my_host(ike_sa, host);
host = this->remote->clone(this->remote);
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 0a7c52a74..d9e4ca582 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -489,7 +489,7 @@ METHOD(ike_sa_t, send_keepalive, void,
data.len = 1;
packet->set_data(packet, data);
DBG1(DBG_IKE, "sending keep alive");
- charon->sender->send(charon->sender, packet);
+ charon->sender->send_no_marker(charon->sender, packet);
diff = 0;
}
job = send_keepalive_job_create(this->ike_sa_id);
@@ -845,9 +845,11 @@ METHOD(ike_sa_t, float_ports, void,
private_ike_sa_t *this)
{
/* do not switch if we have a custom port from MOBIKE/NAT */
- if (this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT)
+ if (this->my_host->get_port(this->my_host) ==
+ charon->socket->get_port(charon->socket, FALSE))
{
- this->my_host->set_port(this->my_host, IKEV2_NATT_PORT);
+ this->my_host->set_port(this->my_host,
+ charon->socket->get_port(charon->socket, TRUE));
}
if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT)
{
@@ -1054,7 +1056,7 @@ static void resolve_hosts(private_ike_sa_t *this)
if (this->local_host)
{
host = this->local_host->clone(this->local_host);
- host->set_port(host, IKEV2_UDP_PORT);
+ host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
}
else
{
@@ -2239,7 +2241,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
}
this->task_manager = task_manager_create(&this->public);
- this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
+ this->my_host->set_port(this->my_host,
+ charon->socket->get_port(charon->socket, FALSE));
if (!this->task_manager || !this->keymat)
{
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
index 8228d016a..bda1d2afb 100644
--- a/src/libcharon/sa/ikev1/tasks/informational.c
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -116,7 +116,8 @@ METHOD(task_t, process_r, status_t,
notify_type_names, type, redirect);
/* Cisco boxes reject the first message from 4500 */
me = this->ike_sa->get_my_host(this->ike_sa);
- me->set_port(me, IKEV2_UDP_PORT);
+ me->set_port(me, charon->socket->get_port(
+ charon->socket, FALSE));
this->ike_sa->set_other_host(this->ike_sa, redirect);
this->ike_sa->reauth(this->ike_sa);
enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 90c38666b..133bc296e 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -271,13 +271,17 @@ static void update_children(private_ike_mobike_t *this)
/**
* Apply the port of the old host, if its ip equals the new, use port otherwise.
*/
-static void apply_port(host_t *host, host_t *old, u_int16_t port)
+static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
{
if (host->ip_equals(host, old))
{
port = old->get_port(old);
}
- else if (port == IKEV2_UDP_PORT)
+ else if (local && port == charon->socket->get_port(charon->socket, FALSE))
+ {
+ port = charon->socket->get_port(charon->socket, TRUE);
+ }
+ else if (!local && port == IKEV2_UDP_PORT)
{
port = IKEV2_NATT_PORT;
}
@@ -314,9 +318,9 @@ METHOD(ike_mobike_t, transmit, void,
continue;
}
/* reuse port for an active address, 4500 otherwise */
- apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg));
+ apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
other = other->clone(other);
- apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg));
+ apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
copy = packet->clone(packet);
copy->set_source(copy, me);
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index b6bc5d92e..650cb1e9e 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -294,6 +294,16 @@ METHOD(kernel_interface_t, bypass_socket, bool,
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, get_address_by_ts, status_t,
private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
{
@@ -539,6 +549,7 @@ kernel_interface_t *kernel_interface_create()
.add_route = _add_route,
.del_route = _del_route,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
.get_address_by_ts = _get_address_by_ts,
.add_ipsec_interface = _add_ipsec_interface,
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index 991cfafd0..37b72f8bb 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -361,11 +361,23 @@ struct kernel_interface_t {
*
* @param fd socket file descriptor to setup policy for
* @param family protocol family of the socket
- * @return TRUE of policy set up successfully
+ * @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
*/
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
index 852f0560c..500a77cad 100644
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ b/src/libhydra/kernel/kernel_ipsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -403,6 +403,17 @@ struct kernel_ipsec_t {
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);
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
index 7e58cf30b..5f077b234 100644
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -2537,13 +2537,6 @@ static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8
return SUCCESS;
}
-METHOD(kernel_ipsec_t, bypass_socket, bool,
- private_kernel_klips_ipsec_t *this, int fd, int family)
-{
- /* KLIPS does not need a bypass policy for IKE */
- return TRUE;
-}
-
METHOD(kernel_ipsec_t, destroy, void,
private_kernel_klips_ipsec_t *this)
{
@@ -2585,7 +2578,10 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create()
.query_policy = _query_policy,
.del_policy = _del_policy,
.flush_policies = (void*)return_failed,
- .bypass_socket = _bypass_socket,
+ /* KLIPS does not need a bypass policy for IKE */
+ .bypass_socket = (void*)return_true,
+ /* KLIPS does not need enabling UDP decap explicitly */
+ .enable_udp_decap = (void*)return_true,
.destroy = _destroy,
},
},
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index b46450c38..73d290051 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -58,6 +58,20 @@
#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
+
/** Default priority of installed policies */
#define PRIO_BASE 512
@@ -2607,6 +2621,19 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
return TRUE;
}
+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)
{
@@ -2654,6 +2681,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
.del_policy = _del_policy,
.flush_policies = _flush_policies,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
.destroy = _destroy,
},
},
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index dfe10f93f..13422670a 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -51,6 +51,9 @@
#include <unistd.h>
#include <time.h>
#include <errno.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
#include "kernel_pfkey_ipsec.h"
@@ -99,6 +102,20 @@
#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
+
/** default priority of installed policies */
#define PRIO_BASE 512
@@ -2488,6 +2505,30 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
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__ */
+ if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &port,
+ sizeof(port)) != 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)
{
@@ -2532,6 +2573,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
.del_policy = _del_policy,
.flush_policies = _flush_policies,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
.destroy = _destroy,
},
},
diff --git a/src/libipsec/Android.mk b/src/libipsec/Android.mk
new file mode 100644
index 000000000..99ff69106
--- /dev/null
+++ b/src/libipsec/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+ipsec.c ipsec.h
+
+# build libipsec ---------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/include \
+ $(strongswan_PATH)/src/libhydra \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libipsec
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am
new file mode 100644
index 000000000..0b8faf724
--- /dev/null
+++ b/src/libipsec/Makefile.am
@@ -0,0 +1,20 @@
+ipseclib_LTLIBRARIES = libipsec.la
+
+libipsec_la_SOURCES = \
+ipsec.c ipsec.h
+
+libipsec_la_LIBADD =
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+EXTRA_DIST = Android.mk
+
+# build optional plugins
+########################
+
+if MONOLITHIC
+SUBDIRS =
+else
+SUBDIRS = .
+endif
+
diff --git a/src/libipsec/ipsec.c b/src/libipsec/ipsec.c
new file mode 100644
index 000000000..add3b463a
--- /dev/null
+++ b/src/libipsec/ipsec.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ipsec.h"
+
+#include <debug.h>
+
+typedef struct private_ipsec_t private_ipsec_t;
+
+/**
+ * Private additions to ipsec_t.
+ */
+struct private_ipsec_t {
+
+ /**
+ * Public members of ipsec_t.
+ */
+ ipsec_t public;
+};
+
+/**
+ * Single instance of ipsec_t.
+ */
+ipsec_t *ipsec;
+
+/**
+ * Described in header.
+ */
+void libipsec_deinit()
+{
+ private_ipsec_t *this = (private_ipsec_t*)ipsec;
+ free(this);
+ ipsec = NULL;
+}
+
+/**
+ * Described in header.
+ */
+bool libipsec_init()
+{
+ private_ipsec_t *this;
+
+ INIT(this,
+ .public = {
+ },
+ );
+ ipsec = &this->public;
+
+ if (lib->integrity &&
+ !lib->integrity->check(lib->integrity, "libipsec", libipsec_init))
+ {
+ DBG1(DBG_LIB, "integrity check of libipsec failed");
+ return FALSE;
+ }
+ return TRUE;
+}
+
diff --git a/src/libipsec/ipsec.h b/src/libipsec/ipsec.h
new file mode 100644
index 000000000..80bef5426
--- /dev/null
+++ b/src/libipsec/ipsec.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup libipsec libipsec
+ *
+ * @addtogroup libipsec
+ * @{
+ */
+
+#ifndef IPSEC_H_
+#define IPSEC_H_
+
+typedef struct ipsec_t ipsec_t;
+
+#include <library.h>
+
+/**
+ * User space IPsec implementation.
+ */
+struct ipsec_t {
+
+};
+
+/**
+ * The single instance of ipsec_t.
+ *
+ * Set between calls to libipsec_init() and libipsec_deinit() calls.
+ */
+extern ipsec_t *ipsec;
+
+/**
+ * Initialize libipsec.
+ *
+ * @return FALSE if integrity check failed
+ */
+bool libipsec_init();
+
+/**
+ * Deinitialize libipsec.
+ */
+void libipsec_deinit();
+
+#endif /** IPSEC_H_ @}*/
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index ae5a7733e..8cba58816 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -58,7 +58,7 @@ LOCAL_SRC_FILES += $(call add_plugin, nonce)
LOCAL_SRC_FILES += $(call add_plugin, openssl)
ifneq ($(call plugin_enabled, openssl),)
-LOCAL_C_INCLUDES += external/openssl/include
+LOCAL_C_INCLUDES += $(openssl_PATH)
LOCAL_SHARED_LIBRARIES += libcrypto
endif
diff --git a/src/libstrongswan/debug.c b/src/libstrongswan/debug.c
index 985ce6a2a..e8c9e6b98 100644
--- a/src/libstrongswan/debug.c
+++ b/src/libstrongswan/debug.c
@@ -34,6 +34,7 @@ ENUM(debug_names, DBG_DMN, DBG_LIB,
"PTS",
"TLS",
"APP",
+ "ESP",
"LIB",
);
@@ -54,6 +55,7 @@ ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
"pts",
"tls",
"app",
+ "esp",
"lib",
);
diff --git a/src/libstrongswan/debug.h b/src/libstrongswan/debug.h
index 65e55a639..ff4b4a1e9 100644
--- a/src/libstrongswan/debug.h
+++ b/src/libstrongswan/debug.h
@@ -64,6 +64,8 @@ enum debug_t {
DBG_TLS,
/** applications other than daemons */
DBG_APP,
+ /** libipsec */
+ DBG_ESP,
/** libstrongswan */
DBG_LIB,
/** number of groups */
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index d5777e35b..95a0bfc02 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -250,8 +250,11 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file,
this->plugins->insert_last(this->plugins, entry);
return TRUE;
case NOT_FOUND:
- /* try to load the plugin from a file */
- break;
+ if (file)
+ { /* try to load the plugin from a file */
+ break;
+ }
+ /* fall-through */
default:
return FALSE;
}
@@ -651,16 +654,18 @@ METHOD(plugin_loader_t, load_plugins, bool,
char *token;
bool critical_failed = FALSE;
+#ifdef PLUGINDIR
if (path == NULL)
{
path = PLUGINDIR;
}
+#endif /* PLUGINDIR */
enumerator = enumerator_create_token(list, " ", " ");
while (!critical_failed && enumerator->enumerate(enumerator, &token))
{
bool critical = FALSE;
- char file[PATH_MAX];
+ char buf[PATH_MAX], *file = NULL;
int len;
token = strdup(token);
@@ -675,10 +680,14 @@ METHOD(plugin_loader_t, load_plugins, bool,
free(token);
continue;
}
- if (snprintf(file, sizeof(file), "%s/libstrongswan-%s.so",
- path, token) >= sizeof(file))
+ if (path)
{
- return FALSE;
+ if (snprintf(buf, sizeof(buf), "%s/libstrongswan-%s.so",
+ path, token) >= sizeof(buf))
+ {
+ return FALSE;
+ }
+ file = buf;
}
if (!load_plugin(this, token, file, critical) && critical)
{
diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c
index b26fbebb4..8977cd9ed 100644
--- a/src/libstrongswan/settings.c
+++ b/src/libstrongswan/settings.c
@@ -1117,14 +1117,21 @@ static bool load_files_internal(private_settings_t *this, section_t *parent,
char *pattern, bool merge)
{
char *text;
- linked_list_t *contents = linked_list_create();
- section_t *section = section_create(NULL);
+ linked_list_t *contents;
+ section_t *section;
if (pattern == NULL)
{
+#ifdef STRONGSWAN_CONF
pattern = STRONGSWAN_CONF;
+#else
+ return FALSE;
+#endif
}
+ contents = linked_list_create();
+ section = section_create(NULL);
+
if (!parse_files(contents, NULL, 0, pattern, section))
{
contents->destroy_function(contents, (void*)free);
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 5dc7f0436..03890b517 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -407,7 +407,7 @@ static void exit_usage(char *error)
printf(" where: START and optional END define the clients source IP\n");
printf(" Set loglevel for a logging type:\n");
printf(" stroke loglevel TYPE LEVEL\n");
- printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib\n");
+ printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n");
printf(" LEVEL is -1|0|1|2|3|4\n");
printf(" Show connection status:\n");
printf(" stroke status\n");