Merge branch 'android-ndk'
This branch comes with some preliminary changes for the user-land IPsec implementation and the Android App. One important change is that the UDP ports used by the socket-default plugin were made configurable (either via ./configure or strongswan.conf). Also, the plugin does randomly allocate a port if it is configured to 0, which is useful for client implementations. A consequence of these changes is that the local UDP port used when creating ike_cfg_t objects has to be fetched from the socket.
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
/Android.mk
|
||||
/Android.common.mk
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
|
||||
@@ -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@"
|
||||
|
||||
@@ -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"
|
||||
@@ -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 \
|
||||
|
||||
+4
-4
@@ -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 > $@
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,10 @@ if USE_LIBHYDRA
|
||||
SUBDIRS += libhydra
|
||||
endif
|
||||
|
||||
if USE_LIBIPSEC
|
||||
SUBDIRS += libipsec
|
||||
endif
|
||||
|
||||
if USE_SIMAKA
|
||||
SUBDIRS += libsimaka
|
||||
endif
|
||||
|
||||
@@ -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,
|
||||
|
||||
+2
-1
@@ -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 }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1,4 @@
|
||||
bin/
|
||||
gen/
|
||||
libs/
|
||||
obj/
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
openssl
|
||||
strongswan
|
||||
vstr/libvstr.a
|
||||
vstr/include
|
||||
@@ -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 \
|
||||
))
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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 *;
|
||||
}
|
||||
@@ -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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+17
-2
@@ -178,15 +178,30 @@ 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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -92,6 +93,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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
@@ -54,6 +55,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
|
||||
*/
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -43,6 +44,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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
@@ -67,6 +67,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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -52,6 +52,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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#include "android_plugin.h"
|
||||
#include "android_logger.h"
|
||||
#include "android_handler.h"
|
||||
#include "android_creds.h"
|
||||
#include "android_service.h"
|
||||
@@ -35,11 +34,6 @@ struct private_android_plugin_t {
|
||||
*/
|
||||
android_plugin_t public;
|
||||
|
||||
/**
|
||||
* Android specific logger
|
||||
*/
|
||||
android_logger_t *logger;
|
||||
|
||||
/**
|
||||
* Android specific DNS 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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
|
||||
+12
-12
@@ -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;
|
||||
+9
-9
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,59 +571,72 @@ 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));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
|
||||
if (this->ipv4 == 0)
|
||||
{
|
||||
DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ipv4_natt = open_socket(this, AF_INET, IKEV2_NATT_PORT);
|
||||
if (this->ipv4_natt == 0)
|
||||
{
|
||||
DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
|
||||
}
|
||||
DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
|
||||
"port randomly");
|
||||
this->natt = 0;
|
||||
}
|
||||
|
||||
this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT);
|
||||
/* 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 IPv6 socket, IPv6 disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ipv6_natt = open_socket(this, AF_INET6, IKEV2_NATT_PORT);
|
||||
this->ipv6_natt = open_socket(this, AF_INET6, &this->natt);
|
||||
if (this->ipv6_natt == 0)
|
||||
{
|
||||
DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
|
||||
}
|
||||
}
|
||||
|
||||
this->ipv4 = open_socket(this, AF_INET, &this->port);
|
||||
if (this->ipv4 == 0)
|
||||
{
|
||||
DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ipv4_natt = open_socket(this, AF_INET, &this->natt);
|
||||
if (this->ipv4_natt == 0)
|
||||
{
|
||||
DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->ipv4 && !this->ipv6)
|
||||
{
|
||||
DBG1(DBG_NET, "could not create any sockets");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,10 +361,22 @@ 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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -402,6 +402,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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
);
|
||||
|
||||
|
||||
@@ -64,6 +64,8 @@ enum debug_t {
|
||||
DBG_TLS,
|
||||
/** applications other than daemons */
|
||||
DBG_APP,
|
||||
/** libipsec */
|
||||
DBG_ESP,
|
||||
/** libstrongswan */
|
||||
DBG_LIB,
|
||||
/** number of groups */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-1
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user