Callback for ESP packets added to receiver.
authorTobias Brunner <tobias@strongswan.org>
Thu, 23 Feb 2012 14:36:02 +0000 (15:36 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 13:12:24 +0000 (15:12 +0200)
src/libcharon/network/receiver.c
src/libcharon/network/receiver.h

index 6a39489..81dfb70 100644 (file)
@@ -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];
@@ -433,7 +447,16 @@ static job_requeue_t receive_packets(private_receiver_t *this)
                }
                else
                {       /* this seems to be an ESP packet */
-                       packet->destroy(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;
                }
        }
@@ -536,11 +559,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);
 }
 
@@ -554,8 +599,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,
        );
index 1d9d487..93b3d3c 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
 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);
 };
 
 /**