implemented a simple IP blocking filter in receiver thread
authorMartin Willi <martin@strongswan.org>
Wed, 28 Mar 2007 09:23:03 +0000 (09:23 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 28 Mar 2007 09:23:03 +0000 (09:23 -0000)
src/charon/threads/receiver.c
src/charon/threads/receiver.h

index 09b1739..a974766 100644 (file)
 #include <queues/jobs/job.h>
 #include <queues/jobs/incoming_packet_job.h>
 
+typedef struct block_t block_t;
+
+/**
+ * entry for a blocked IP
+ */
+struct block_t {
+
+       /**
+        * IP address to block
+        */
+       host_t *ip;
+       
+       /**
+        * lifetime for this block
+        */
+       u_int32_t timeout;
+};
+
+/**
+ * destroy a block_t
+ */
+static void block_destroy(block_t *block)
+{
+       block->ip->destroy(block->ip);
+       free(block);
+}
 
 typedef struct private_receiver_t private_receiver_t;
 
@@ -49,6 +75,16 @@ struct private_receiver_t {
          * Assigned thread.
          */
         pthread_t assigned_thread;
+        
+        /**
+         * List of blocked IPs
+         */
+        linked_list_t *blocks;
+        
+        /**
+         * mutex to exclusively access block list
+         */
+        pthread_mutex_t mutex;
 };
 
 /**
@@ -56,46 +92,105 @@ struct private_receiver_t {
  */
 static void receive_packets(private_receiver_t * this)
 {
-       packet_t * current_packet;
-       job_t *current_job;
+       packet_t *packet;
+       job_t *job;
        
        /* cancellation disabled by default */
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-       
        DBG1(DBG_NET, "receiver thread running, thread_ID: %06u", 
                 (int)pthread_self());
        
        while (TRUE)
        {
-               while (charon->socket->receive(charon->socket,&current_packet) == SUCCESS)
+               if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
                {
-                       DBG2(DBG_NET, "creating job from packet");
-                       current_job = (job_t *) incoming_packet_job_create(current_packet);
+                       DBG1(DBG_NET, "receiving from socket failed!");
+                       continue;
+               }
+               
+               if (this->blocks->get_count(this->blocks))
+               {
+                       iterator_t *iterator;
+                       block_t *blocked;
+                       bool found = FALSE;
+                       u_int32_t now = time(NULL);
                        
-                       charon->job_queue->add(charon->job_queue,current_job);
+                       pthread_mutex_lock(&this->mutex);
+                       iterator = this->blocks->create_iterator(this->blocks, TRUE);
+                       while (iterator->iterate(iterator, (void**)&blocked))
+                       {
+                               if (now > blocked->timeout)
+                               {
+                                       /* block expired, remove */
+                                       iterator->remove(iterator);
+                                       block_destroy(blocked);
+                                       continue;
+                               }
+                       
+                               if (!blocked->ip->ip_equals(blocked->ip, 
+                                                                                       packet->get_source(packet)))
+                               {
+                                       /* no match, get next */
+                                       continue;
+                               }
+                               
+                               /* IP is blocked */
+                               DBG2(DBG_NET, "received packets source address %H blocked", 
+                                        blocked->ip);
+                               packet->destroy(packet);
+                               found = TRUE;
+                               break;
+                       }
+                       iterator->destroy(iterator);
+                       pthread_mutex_unlock(&this->mutex);
+                       if (found)
+                       {
+                               /* get next packet */
+                               continue;
+                       }
                }
-               /* bad bad, TODO: rebuild the socket ? */
-               DBG1(DBG_NET, "receiving from socket failed!");
+               
+               DBG2(DBG_NET, "creating job from packet");
+               job = (job_t *) incoming_packet_job_create(packet);
+               charon->job_queue->add(charon->job_queue, job);
        }
 }
 
 /**
+ * Implementation of receiver_t.block
+ */
+static void block(private_receiver_t *this, host_t *ip, u_int32_t seconds)
+{
+       block_t *blocked = malloc_thing(block_t);
+       
+       blocked->ip = ip->clone(ip);
+       blocked->timeout = time(NULL) + seconds;
+       DBG1(DBG_NET, "blocking %H for %ds", ip, seconds);
+       
+       pthread_mutex_lock(&this->mutex);
+       this->blocks->insert_last(this->blocks, blocked);
+       pthread_mutex_unlock(&this->mutex);
+}
+
+/**
  * Implementation of receiver_t.destroy.
  */
 static void destroy(private_receiver_t *this)
 {
        pthread_cancel(this->assigned_thread);
        pthread_join(this->assigned_thread, NULL);
+       this->blocks->destroy_function(this->blocks, (void*)block_destroy);
        free(this);
 }
 
 /*
  * Described in header.
  */
-receiver_t * receiver_create()
+receiver_t *receiver_create()
 {
        private_receiver_t *this = malloc_thing(private_receiver_t);
 
+       this->public.block = (void(*)(receiver_t*,host_t*,u_int32_t)) block;
        this->public.destroy = (void(*)(receiver_t*)) destroy;
        
        if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))receive_packets, this) != 0)
@@ -104,5 +199,8 @@ receiver_t * receiver_create()
                charon->kill(charon, "unable to create receiver thread");
        }
 
+       pthread_mutex_init(&this->mutex, NULL);
+       this->blocks = linked_list_create();
+
        return &(this->public);
 }
index ff0971c..3be40e9 100644 (file)
 typedef struct receiver_t receiver_t;
 
 #include <library.h>
+#include <utils/host.h>
 
 /**
  * @brief Receives packets from the socket and adds them to the job queue.
  * 
  * The receiver starts a thread, wich reads on the blocking socket. If 
- * data is available, a packet_t object is created , wrapped
+ * data is available, a packet_t object is created, wrapped
  * in an incoming_packet_job_t and added to the job queue.
  * 
  * @b Constructors:
@@ -43,6 +44,15 @@ typedef struct receiver_t receiver_t;
 struct receiver_t {
 
        /**
+        * @brief Block packets coming from a specific address.
+        *
+        * @param receiver      receiver object
+        * @param ip            IP address to block
+        * @param seconds       for how long to block ip
+        */
+       void (*block) (receiver_t *receiver, host_t *ip, u_int32_t seconds);
+       
+       /**
         * @brief Destroys a receiver_t object.
         *
         * @param receiver      receiver object