aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/network/receiver.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2012-08-13 10:39:34 +0200
committerTobias Brunner <tobias@strongswan.org>2012-08-13 10:45:39 +0200
commite4ef4c9877d5ccb773ace0edf655351428c39572 (patch)
tree9b3349ad0cafc1acebafb2ff2dc78a031f28c555 /src/libcharon/network/receiver.c
parent000668d3081422a3ac06fe16f038a4b1d6700f96 (diff)
parent6fbf4472ea785f3c75d278b1a7400534989bf26a (diff)
downloadstrongswan-e4ef4c9877d5ccb773ace0edf655351428c39572.tar.bz2
strongswan-e4ef4c9877d5ccb773ace0edf655351428c39572.tar.xz
Merge branch 'android-ndk'
This branch comes with some preliminary changes for the user-land IPsec implementation and the Android App. One important change is that the UDP ports used by the socket-default plugin were made configurable (either via ./configure or strongswan.conf). Also, the plugin does randomly allocate a port if it is configured to 0, which is useful for client implementations. A consequence of these changes is that the local UDP port used when creating ike_cfg_t objects has to be fetched from the socket.
Diffstat (limited to 'src/libcharon/network/receiver.c')
-rw-r--r--src/libcharon/network/receiver.c83
1 files changed, 82 insertions, 1 deletions
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,
);