diff --git a/src/charon/threads/receiver.c b/src/charon/threads/receiver.c index 09b1739c4..a97476621 100644 --- a/src/charon/threads/receiver.c +++ b/src/charon/threads/receiver.c @@ -33,6 +33,32 @@ #include #include +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,29 +92,86 @@ 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,¤t_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); - - charon->job_queue->add(charon->job_queue,current_job); + DBG1(DBG_NET, "receiving from socket failed!"); + continue; } - /* bad bad, TODO: rebuild the socket ? */ - DBG1(DBG_NET, "receiving from socket failed!"); + + if (this->blocks->get_count(this->blocks)) + { + iterator_t *iterator; + block_t *blocked; + bool found = FALSE; + u_int32_t now = time(NULL); + + 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; + } + } + + 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. */ @@ -86,16 +179,18 @@ 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); } diff --git a/src/charon/threads/receiver.h b/src/charon/threads/receiver.h index ff0971cad..3be40e901 100644 --- a/src/charon/threads/receiver.h +++ b/src/charon/threads/receiver.h @@ -27,12 +27,13 @@ typedef struct receiver_t receiver_t; #include +#include /** * @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: @@ -42,6 +43,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. *