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