aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api_blacklist.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
commit541caf3dec54aaee621fed935e667f9ee423ef31 (patch)
tree6f80958e68541ce071bc557bbfc168644963c473 /src/transport/transport_api_blacklist.c
parente8bc962b2ed43e194ba124537573da236786e82c (diff)
downloadgnunet-541caf3dec54aaee621fed935e667f9ee423ef31.tar.gz
gnunet-541caf3dec54aaee621fed935e667f9ee423ef31.zip
towards fixing blacklisting APIs and implementation
Diffstat (limited to 'src/transport/transport_api_blacklist.c')
-rw-r--r--src/transport/transport_api_blacklist.c385
1 files changed, 149 insertions, 236 deletions
diff --git a/src/transport/transport_api_blacklist.c b/src/transport/transport_api_blacklist.c
index c8838f1b6..5d2d616e8 100644
--- a/src/transport/transport_api_blacklist.c
+++ b/src/transport/transport_api_blacklist.c
@@ -36,7 +36,7 @@
36/** 36/**
37 * Handle for blacklisting requests. 37 * Handle for blacklisting requests.
38 */ 38 */
39struct GNUNET_TRANSPORT_BlacklistRequest 39struct GNUNET_TRANSPORT_Blacklist
40{ 40{
41 41
42 /** 42 /**
@@ -45,342 +45,255 @@ struct GNUNET_TRANSPORT_BlacklistRequest
45 struct GNUNET_CLIENT_Connection * client; 45 struct GNUNET_CLIENT_Connection * client;
46 46
47 /** 47 /**
48 * Function to call when done. 48 * Scheduler to use.
49 */
50 GNUNET_SCHEDULER_Task cont;
51
52 /**
53 * Clsoure for 'cont'.
54 */ 49 */
55 void *cont_cls; 50 struct GNUNET_SCHEDULER_Handle *sched;
56 51
57 /** 52 /**
58 * Scheduler to use. 53 * Configuration to use.
59 */ 54 */
60 struct GNUNET_SCHEDULER_Handle *sched; 55 const struct GNUNET_CONFIGURATION_Handle *cfg;
61 56
62 /** 57 /**
63 * Pending handle for the blacklisting request. 58 * Pending handle for the current request.
64 */ 59 */
65 struct GNUNET_CLIENT_TransmitHandle *th; 60 struct GNUNET_CLIENT_TransmitHandle *th;
66 61
67 /** 62 /**
68 * How long should 'peer' be blacklisted? 63 * Function to call for determining if a peer is allowed
64 * to communicate with us.
69 */ 65 */
70 struct GNUNET_TIME_Absolute duration; 66 GNUNET_TRANSPORT_BlacklistCallback cb;
71 67
72 /** 68 /**
73 * Which peer is being blacklisted? 69 * Closure for 'cb'.
70 */
71 void *cb_cls;
72
73 /**
74 * Peer currently under consideration.
74 */ 75 */
75 struct GNUNET_PeerIdentity peer; 76 struct GNUNET_PeerIdentity peer;
76 77
77}; 78};
78 79
79 80
80/** 81/**
81 * Function called to notify a client about the socket 82 * Establish blacklist connection to transport service.
82 * begin ready to queue more data. "buf" will be
83 * NULL and "size" zero if the socket was closed for
84 * writing in the meantime.
85 * 83 *
86 * @param cls closure 84 * @param br overall handle
87 * @param size number of bytes available in buf
88 * @param buf where the callee should write the message
89 * @return number of bytes written to buf
90 */ 85 */
91static size_t 86static void
92transmit_blacklist_request (void *cls, 87reconnect (struct GNUNET_TRANSPORT_Blacklist *br);
93 size_t size, void *buf)
94{
95 struct GNUNET_TRANSPORT_BlacklistRequest *br = cls;
96 struct BlacklistMessage req;
97
98 if (buf == NULL)
99 {
100 GNUNET_SCHEDULER_add_continuation (br->sched,
101 br->cont,
102 br->cont_cls,
103 GNUNET_SCHEDULER_REASON_TIMEOUT);
104 GNUNET_free (br);
105 return 0;
106 }
107 req.header.size = htons (sizeof (req));
108 req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST);
109 req.reserved = htonl (0);
110 req.peer = br->peer;
111 req.until = GNUNET_TIME_absolute_hton (br->duration);
112 memcpy (buf, &req, sizeof (req));
113 GNUNET_SCHEDULER_add_continuation (br->sched,
114 br->cont,
115 br->cont_cls,
116 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
117 GNUNET_free (br);
118 return sizeof (req);
119}
120 88
121 89
122/** 90/**
123 * Blacklist a peer for a given period of time. All connections 91 * Send our reply to a blacklisting request.
124 * (inbound and outbound) to a peer that is blacklisted will be
125 * dropped (as soon as we learn who the connection is for). A second
126 * call to this function for the same peer overrides previous
127 * blacklisting requests.
128 * 92 *
129 * @param sched scheduler to use 93 * @param br our overall context
130 * @param cfg configuration to use
131 * @param peer identity of peer to blacklist
132 * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to
133 * re-enable connections
134 * @param timeout when should this operation (trying to establish the
135 * blacklisting time out)
136 * @param cont continuation to call once the request has been processed
137 * @param cont_cls closure for cont
138 * @return NULL on error, otherwise handle for cancellation
139 */ 94 */
140struct GNUNET_TRANSPORT_BlacklistRequest * 95static void
141GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched, 96reply (struct GNUNET_TRANSPORT_Blacklist *br);
142 const struct GNUNET_CONFIGURATION_Handle *cfg,
143 const struct GNUNET_PeerIdentity *peer,
144 struct GNUNET_TIME_Relative duration,
145 struct GNUNET_TIME_Relative timeout,
146 GNUNET_SCHEDULER_Task cont,
147 void *cont_cls)
148{
149 struct GNUNET_CLIENT_Connection * client;
150 struct GNUNET_TRANSPORT_BlacklistRequest *ret;
151
152 client = GNUNET_CLIENT_connect (sched, "transport", cfg);
153 if (NULL == client)
154 return NULL;
155 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistRequest));
156 ret->client = client;
157 ret->peer = *peer;
158 ret->duration = GNUNET_TIME_relative_to_absolute (duration);
159 ret->sched = sched;
160 ret->cont = cont;
161 ret->cont_cls = cont_cls;
162 ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
163 sizeof (struct BlacklistMessage),
164 timeout,
165 GNUNET_YES,
166 &transmit_blacklist_request,
167 ret);
168 GNUNET_assert (NULL != ret->th);
169 return ret;
170}
171 97
172 98
173/** 99/**
174 * Abort transmitting the blacklist request. Note that this function 100 * Handle blacklist queries.
175 * is NOT for removing a peer from the blacklist (for that, call
176 * GNUNET_TRANSPORT_blacklist with a duration of zero). This function
177 * is only for aborting the transmission of a blacklist request
178 * (i.e. because of shutdown).
179 * 101 *
180 * @param br handle of the request that is to be cancelled 102 * @param cls our overall handle
103 * @param msg query
181 */ 104 */
182void 105static void
183GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * br) 106query_handler (void *cls,
184{ 107 const struct GNUNET_MessageHeader *msg)
185 GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
186 GNUNET_free (br);
187}
188
189
190/**
191 * Handle for blacklist notifications.
192 */
193struct GNUNET_TRANSPORT_BlacklistNotification
194{ 108{
195 109 struct GNUNET_TRANSPORT_Blacklist *br = cls;
196 /** 110 const struct BlacklistMessage *bm;
197 * Function to call whenever there is a change.
198 */
199 GNUNET_TRANSPORT_BlacklistCallback notify;
200
201 /**
202 * Closure for notify.
203 */
204 void *notify_cls;
205
206 /**
207 * Scheduler to use.
208 */
209 struct GNUNET_SCHEDULER_Handle *sched;
210
211 /**
212 * Configuration to use.
213 */
214 const struct GNUNET_CONFIGURATION_Handle *cfg;
215 111
216 /** 112 if ( (ntohs(msg->size) != sizeof (struct BlacklistMessage)) ||
217 * Connection to transport service. 113 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY) )
218 */ 114 {
219 struct GNUNET_CLIENT_Connection * client; 115 reconnect (br);
220 116 return;
221 /** 117 }
222 * Pending handle for the notification request. 118 bm = (const struct BlacklistMessage *)msg;
223 */ 119 GNUNET_break (0 == ntohl (bm->is_allowed));
224 struct GNUNET_CLIENT_TransmitHandle *th; 120 br->peer = bm->peer;
225}; 121 reply (br);
122}
226 123
227 124
228/** 125/**
229 * Send a request to receive blacklisting notifications 126 * Receive blacklist queries from transport service.
230 * 127 *
231 * @param bn context to initialize 128 * @param br overall handle
232 */ 129 */
233static void 130static void
234request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn); 131receive (struct GNUNET_TRANSPORT_Blacklist *br)
132{
133 GNUNET_CLIENT_receive (br->client,
134 &query_handler,
135 br,
136 GNUNET_TIME_UNIT_FOREVER_REL);
137}
235 138
236 139
237/** 140/**
238 * Destroy the existing connection to the transport service and 141 * Transmit the blacklist initialization request to the service.
239 * setup a new one (the existing one had serious problems). 142 *
240 * 143 * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
241 * @param bn context to re-initialize 144 * @param size number of bytes available in buf
145 * @param buf where the callee should write the message
146 * @return number of bytes written to buf
242 */ 147 */
243static void 148static size_t
244retry_get_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) 149transmit_blacklist_init (void *cls,
150 size_t size, void *buf)
245{ 151{
246 GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO); 152 struct GNUNET_TRANSPORT_Blacklist *br = cls;
247 bn->client = GNUNET_CLIENT_connect (bn->sched, "transport", bn->cfg); 153 struct GNUNET_MessageHeader req;
248 request_notifications (bn); 154
155 if (buf == NULL)
156 {
157 reconnect (br);
158 return 0;
159 }
160 req.size = htons (sizeof (struct GNUNET_MessageHeader));
161 req.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT);
162 memcpy (buf, &req, sizeof (req));
163 receive (br);
164 return sizeof (req);
249} 165}
250 166
251 167
252/** 168/**
253 * Function called whenever we get a blacklisting notification. 169 * Establish blacklist connection to transport service.
254 * Pass it on to the callback and wait for more.
255 * 170 *
256 * @param cls our 'struct GNUNET_TRANSPORT_BlacklistNotification *' 171 * @param br overall handle
257 * @param msg the blacklisting notification, NULL on error
258 */ 172 */
259static void 173static void
260recv_blacklist_info (void *cls, 174reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
261 const struct GNUNET_MessageHeader *msg)
262{ 175{
263 struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; 176 if (br->client != NULL)
264 const struct BlacklistMessage *req; 177 GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
265 178 br->client = GNUNET_CLIENT_connect (br->sched,
266 if ( (msg == NULL) || 179 "transport",
267 (sizeof(struct BlacklistMessage) != ntohs(msg->size)) || 180 br->cfg);
268 (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST != ntohs(msg->type)) ) 181 br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
269 { 182 sizeof (struct GNUNET_MessageHeader),
270 retry_get_notifications (bn); 183 GNUNET_TIME_UNIT_FOREVER_REL,
271 return; 184 GNUNET_YES,
272 } 185 &transmit_blacklist_init,
273 req = (const struct BlacklistMessage*) msg; 186 br);
274 bn->notify (bn->notify_cls,
275 &req->peer,
276 GNUNET_TIME_absolute_ntoh (req->until));
277 GNUNET_CLIENT_receive (bn->client,
278 &recv_blacklist_info,
279 bn,
280 GNUNET_TIME_UNIT_FOREVER_REL);
281} 187}
282 188
283 189
284/** 190/**
285 * Function called to notify a client about the socket 191 * Transmit the blacklist response to the service.
286 * begin ready to queue more data. "buf" will be
287 * NULL and "size" zero if the socket was closed for
288 * writing in the meantime.
289 * 192 *
290 * @param cls closure 193 * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
291 * @param size number of bytes available in buf 194 * @param size number of bytes available in buf
292 * @param buf where the callee should write the message 195 * @param buf where the callee should write the message
293 * @return number of bytes written to buf 196 * @return number of bytes written to buf
294 */ 197 */
295static size_t 198static size_t
296transmit_notify_request (void *cls, 199transmit_blacklist_reply (void *cls,
297 size_t size, void *buf) 200 size_t size, void *buf)
298{ 201{
299 struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; 202 struct GNUNET_TRANSPORT_Blacklist *br = cls;
300 struct GNUNET_MessageHeader hdr; 203 struct BlacklistMessage req;
301 204
302 bn->th = NULL;
303 if (buf == NULL) 205 if (buf == NULL)
304 { 206 {
305 retry_get_notifications (bn); 207 reconnect (br);
306 return 0; 208 return 0;
307 } 209 }
308 GNUNET_assert (size >= sizeof(hdr)); 210 req.header.size = htons (sizeof (req));
309 hdr.size = htons (sizeof (hdr)); 211 req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY);
310 hdr.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY); 212 req.is_allowed = htonl (br->cb (br->cb_cls, &br->peer));
311 memcpy (buf, &hdr, sizeof(hdr)); 213 req.peer = br->peer;
312 return sizeof(hdr); 214 memcpy (buf, &req, sizeof (req));
215 receive (br);
216 return sizeof (req);
313} 217}
314 218
315 219
316/** 220/**
317 * Send a request to receive blacklisting notifications 221 * Send our reply to a blacklisting request.
318 * 222 *
319 * @param bn context to initialize 223 * @param br our overall context
320 */ 224 */
321static void 225static void
322request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) 226reply (struct GNUNET_TRANSPORT_Blacklist *br)
323{ 227{
324 GNUNET_assert (bn->client != NULL); 228 br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
325 bn->th = GNUNET_CLIENT_notify_transmit_ready (bn->client, 229 sizeof (struct BlacklistMessage),
326 sizeof (struct GNUNET_MessageHeader),
327 GNUNET_TIME_UNIT_FOREVER_REL, 230 GNUNET_TIME_UNIT_FOREVER_REL,
328 GNUNET_YES, 231 GNUNET_NO,
329 &transmit_notify_request, 232 &transmit_blacklist_reply,
330 bn); 233 br);
331 GNUNET_assert (bn->th != NULL); 234 if (br->th == NULL)
332 GNUNET_CLIENT_receive (bn->client, 235 {
333 &recv_blacklist_info, 236 reconnect (br);
334 bn, 237 return;
335 GNUNET_TIME_UNIT_FOREVER_REL); 238 }
336} 239}
337 240
338 241
339/** 242/**
340 * Call a function whenever a peer's blacklisting status changes. 243 * Install a blacklist callback. The service will be queried for all
244 * existing connections as well as any fresh connections to check if
245 * they are permitted. If the blacklisting callback is unregistered,
246 * all hosts that were denied in the past will automatically be
247 * whitelisted again. Cancelling the blacklist handle is also the
248 * only way to re-enable connections from peers that were previously
249 * blacklisted.
341 * 250 *
342 * @param sched scheduler to use 251 * @param sched scheduler to use
343 * @param cfg configuration to use 252 * @param cfg configuration to use
344 * @param bc function to call on status changes 253 * @param cb callback to invoke to check if connections are allowed
345 * @param bc_cls closure for bc 254 * @param cb_cls closure for cb
346 * @return NULL on error, otherwise handle for cancellation 255 * @return NULL on error, otherwise handle for cancellation
347 */ 256 */
348struct GNUNET_TRANSPORT_BlacklistNotification * 257struct GNUNET_TRANSPORT_Blacklist *
349GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched, 258GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
350 const struct GNUNET_CONFIGURATION_Handle *cfg, 259 const struct GNUNET_CONFIGURATION_Handle *cfg,
351 GNUNET_TRANSPORT_BlacklistCallback bc, 260 GNUNET_TRANSPORT_BlacklistCallback cb,
352 void *bc_cls) 261 void *cb_cls)
353{ 262{
354 struct GNUNET_TRANSPORT_BlacklistNotification *ret;
355 struct GNUNET_CLIENT_Connection * client; 263 struct GNUNET_CLIENT_Connection * client;
264 struct GNUNET_TRANSPORT_Blacklist *ret;
356 265
357 client = GNUNET_CLIENT_connect (sched, "transport", cfg); 266 client = GNUNET_CLIENT_connect (sched, "transport", cfg);
358 if (NULL == client) 267 if (NULL == client)
359 return NULL; 268 return NULL;
360 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistNotification)); 269 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Blacklist));
361 ret->client = client; 270 ret->client = client;
362 ret->sched = sched; 271 ret->sched = sched;
363 ret->cfg = cfg; 272 ret->cfg = cfg;
364 ret->notify = bc; 273 ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
365 ret->notify_cls = bc_cls; 274 sizeof (struct GNUNET_MessageHeader),
366 request_notifications (ret); 275 GNUNET_TIME_UNIT_FOREVER_REL,
276 GNUNET_YES,
277 &transmit_blacklist_init,
278 ret);
367 return ret; 279 return ret;
368} 280}
369 281
370 282
371/** 283/**
372 * Stop calling the notification callback associated with 284 * Abort the blacklist. Note that this function is the only way for
373 * the given blacklist notification. 285 * removing a peer from the blacklist.
374 * 286 *
375 * @param bn handle of the request that is to be cancelled 287 * @param br handle of the request that is to be cancelled
376 */ 288 */
377void 289void
378GNUNET_TRANSPORT_blacklist_notify_cancel (struct GNUNET_TRANSPORT_BlacklistNotification * bn) 290GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br)
379{ 291{
380 if (bn->th != NULL) 292 if (br->th != NULL)
381 GNUNET_CLIENT_notify_transmit_ready_cancel (bn->th); 293 GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
382 GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO); 294 GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
383 GNUNET_free (bn); 295 GNUNET_free (br);
384} 296}
385 297
298
386/* end of transport_api_blacklist.c */ 299/* end of transport_api_blacklist.c */