removed send_queue, handled internally in sender_t know
[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/process_message_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.block
92 */
93 static void block(private_receiver_t *this, host_t *ip, u_int32_t seconds)
94 {
95 block_t *blocked = malloc_thing(block_t);
96
97 blocked->ip = ip->clone(ip);
98 blocked->timeout = time(NULL) + seconds;
99 DBG1(DBG_NET, "blocking %H for %ds", ip, seconds);
100
101 pthread_mutex_lock(&this->mutex);
102 this->blocks->insert_last(this->blocks, blocked);
103 pthread_mutex_unlock(&this->mutex);
104 }
105
106 /**
107 * check if an IP is blocked
108 */
109 static bool is_blocked(private_receiver_t *this, host_t *ip)
110 {
111 bool found = FALSE;
112
113 if (this->blocks->get_count(this->blocks))
114 {
115 iterator_t *iterator;
116 block_t *blocked;
117 u_int32_t now = time(NULL);
118
119 pthread_mutex_lock(&this->mutex);
120 iterator = this->blocks->create_iterator(this->blocks, TRUE);
121 while (iterator->iterate(iterator, (void**)&blocked))
122 {
123 if (now > blocked->timeout)
124 {
125 /* blocking expired, remove */
126 iterator->remove(iterator);
127 block_destroy(blocked);
128 continue;
129 }
130
131 if (!ip->ip_equals(ip, blocked->ip))
132 {
133 /* no match, get next */
134 continue;
135 }
136
137 /* blocked */
138 DBG2(DBG_NET, "received packet source address %H blocked", ip);
139 found = TRUE;
140 break;
141 }
142 iterator->destroy(iterator);
143 pthread_mutex_unlock(&this->mutex);
144 }
145 return found;
146 }
147
148 /**
149 * Implementation of receiver_t.receive_packets.
150 */
151 static void receive_packets(private_receiver_t * this)
152 {
153 packet_t *packet;
154 message_t *message;
155 job_t *job;
156
157 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
158 DBG1(DBG_NET, "receiver thread running, thread_ID: %06u",
159 (int)pthread_self());
160
161 while (TRUE)
162 {
163 if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
164 {
165 DBG1(DBG_NET, "receiving from socket failed!");
166 continue;
167 }
168
169 if (is_blocked(this, packet->get_source(packet)))
170 {
171 packet->destroy(packet);
172 continue;
173 }
174
175 message = message_create_from_packet(packet);
176 if (message->parse_header(message) != SUCCESS)
177 {
178 DBG1(DBG_NET, "received invalid IKE header from %H, ignored",
179 packet->get_source(packet));
180 message->destroy(message);
181 continue;
182 }
183
184 if (message->get_major_version(message) != IKE_MAJOR_VERSION)
185 {
186 DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, "
187 "ignored", message->get_major_version(message),
188 message->get_minor_version(message), packet->get_source(packet));
189 message->destroy(message);
190 continue;
191 }
192
193
194 job = (job_t *)process_message_job_create(message);
195 charon->job_queue->add(charon->job_queue, job);
196 }
197 }
198
199
200 /**
201 * Implementation of receiver_t.destroy.
202 */
203 static void destroy(private_receiver_t *this)
204 {
205 pthread_cancel(this->assigned_thread);
206 pthread_join(this->assigned_thread, NULL);
207 this->blocks->destroy_function(this->blocks, (void*)block_destroy);
208 free(this);
209 }
210
211 /*
212 * Described in header.
213 */
214 receiver_t *receiver_create()
215 {
216 private_receiver_t *this = malloc_thing(private_receiver_t);
217
218 this->public.block = (void(*)(receiver_t*,host_t*,u_int32_t)) block;
219 this->public.destroy = (void(*)(receiver_t*)) destroy;
220
221 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))receive_packets, this) != 0)
222 {
223 free(this);
224 charon->kill(charon, "unable to create receiver thread");
225 }
226
227 pthread_mutex_init(&this->mutex, NULL);
228 this->blocks = linked_list_create();
229
230 return &(this->public);
231 }