a97476621c720455f4b424205f710fa7bc64316f
[strongswan.git] / src / charon / threads / receiver.c
1 /**
2 * @file receiver.c
3 *
4 * @brief Implementation of receiver_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdlib.h>
25 #include <pthread.h>
26
27 #include "receiver.h"
28
29 #include <daemon.h>
30 #include <network/socket.h>
31 #include <network/packet.h>
32 #include <queues/job_queue.h>
33 #include <queues/jobs/job.h>
34 #include <queues/jobs/incoming_packet_job.h>
35
36 typedef struct block_t block_t;
37
38 /**
39 * entry for a blocked IP
40 */
41 struct block_t {
42
43 /**
44 * IP address to block
45 */
46 host_t *ip;
47
48 /**
49 * lifetime for this block
50 */
51 u_int32_t timeout;
52 };
53
54 /**
55 * destroy a block_t
56 */
57 static void block_destroy(block_t *block)
58 {
59 block->ip->destroy(block->ip);
60 free(block);
61 }
62
63 typedef struct private_receiver_t private_receiver_t;
64
65 /**
66 * Private data of a receiver_t object.
67 */
68 struct private_receiver_t {
69 /**
70 * Public part of a receiver_t object.
71 */
72 receiver_t public;
73
74 /**
75 * Assigned thread.
76 */
77 pthread_t assigned_thread;
78
79 /**
80 * List of blocked IPs
81 */
82 linked_list_t *blocks;
83
84 /**
85 * mutex to exclusively access block list
86 */
87 pthread_mutex_t mutex;
88 };
89
90 /**
91 * Implementation of receiver_t.receive_packets.
92 */
93 static void receive_packets(private_receiver_t * this)
94 {
95 packet_t *packet;
96 job_t *job;
97
98 /* cancellation disabled by default */
99 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
100 DBG1(DBG_NET, "receiver thread running, thread_ID: %06u",
101 (int)pthread_self());
102
103 while (TRUE)
104 {
105 if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
106 {
107 DBG1(DBG_NET, "receiving from socket failed!");
108 continue;
109 }
110
111 if (this->blocks->get_count(this->blocks))
112 {
113 iterator_t *iterator;
114 block_t *blocked;
115 bool found = FALSE;
116 u_int32_t now = time(NULL);
117
118 pthread_mutex_lock(&this->mutex);
119 iterator = this->blocks->create_iterator(this->blocks, TRUE);
120 while (iterator->iterate(iterator, (void**)&blocked))
121 {
122 if (now > blocked->timeout)
123 {
124 /* block expired, remove */
125 iterator->remove(iterator);
126 block_destroy(blocked);
127 continue;
128 }
129
130 if (!blocked->ip->ip_equals(blocked->ip,
131 packet->get_source(packet)))
132 {
133 /* no match, get next */
134 continue;
135 }
136
137 /* IP is blocked */
138 DBG2(DBG_NET, "received packets source address %H blocked",
139 blocked->ip);
140 packet->destroy(packet);
141 found = TRUE;
142 break;
143 }
144 iterator->destroy(iterator);
145 pthread_mutex_unlock(&this->mutex);
146 if (found)
147 {
148 /* get next packet */
149 continue;
150 }
151 }
152
153 DBG2(DBG_NET, "creating job from packet");
154 job = (job_t *) incoming_packet_job_create(packet);
155 charon->job_queue->add(charon->job_queue, job);
156 }
157 }
158
159 /**
160 * Implementation of receiver_t.block
161 */
162 static void block(private_receiver_t *this, host_t *ip, u_int32_t seconds)
163 {
164 block_t *blocked = malloc_thing(block_t);
165
166 blocked->ip = ip->clone(ip);
167 blocked->timeout = time(NULL) + seconds;
168 DBG1(DBG_NET, "blocking %H for %ds", ip, seconds);
169
170 pthread_mutex_lock(&this->mutex);
171 this->blocks->insert_last(this->blocks, blocked);
172 pthread_mutex_unlock(&this->mutex);
173 }
174
175 /**
176 * Implementation of receiver_t.destroy.
177 */
178 static void destroy(private_receiver_t *this)
179 {
180 pthread_cancel(this->assigned_thread);
181 pthread_join(this->assigned_thread, NULL);
182 this->blocks->destroy_function(this->blocks, (void*)block_destroy);
183 free(this);
184 }
185
186 /*
187 * Described in header.
188 */
189 receiver_t *receiver_create()
190 {
191 private_receiver_t *this = malloc_thing(private_receiver_t);
192
193 this->public.block = (void(*)(receiver_t*,host_t*,u_int32_t)) block;
194 this->public.destroy = (void(*)(receiver_t*)) destroy;
195
196 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))receive_packets, this) != 0)
197 {
198 free(this);
199 charon->kill(charon, "unable to create receiver thread");
200 }
201
202 pthread_mutex_init(&this->mutex, NULL);
203 this->blocks = linked_list_create();
204
205 return &(this->public);
206 }