aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_blacklist.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-20 19:53:24 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-20 19:53:24 +0000
commit03f0ae4bb10cf55bb9bab601d45fd96c2eb13603 (patch)
tree9089fc11319e7de97c43d2e0bf8e6d9b67836b92 /src/transport/gnunet-service-transport_blacklist.c
parent450982bb56fde81bd512cb21360b809482caf19b (diff)
downloadgnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.tar.gz
gnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.zip
migrating transport service to new MQ API
Diffstat (limited to 'src/transport/gnunet-service-transport_blacklist.c')
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c933
1 files changed, 0 insertions, 933 deletions
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
deleted file mode 100644
index b6c36a6cd..000000000
--- a/src/transport/gnunet-service-transport_blacklist.c
+++ /dev/null
@@ -1,933 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010,2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file transport/gnunet-service-transport_blacklist.c
23 * @brief blacklisting implementation
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 * @details This is the blacklisting component of transport service. With
27 * blacklisting it is possible to deny connections to specific peers of
28 * to use a specific plugin to a specific peer. Peers can be blacklisted using
29 * the configuration or a blacklist client can be asked.
30 *
31 * To blacklist peers using the configuration you have to add a section to your
32 * configuration containing the peer id of the peer to blacklist and the plugin
33 * if required.
34 *
35 * Example:
36 * To blacklist connections to P565... on peer AG2P... using tcp add:
37 * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
38 * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = tcp
39 *
40 * To blacklist connections to P565... on peer AG2P... using all plugins add:
41 * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
42 * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G =
43 *
44 * You can also add a blacklist client usign the blacklist api. On a blacklist
45 * check, blacklisting first checks internally if the peer is blacklisted and
46 * if not, it asks the blacklisting clients. Clients are asked if it is OK to
47 * connect to a peer ID, the plugin is omitted.
48 *
49 * On blacklist check for (peer, plugin)
50 * - Do we have a local blacklist entry for this peer and this plugin?
51 * - YES: disallow connection
52 * - Do we have a local blacklist entry for this peer and all plugins?
53 * - YES: disallow connection
54 * - Does one of the clients disallow?
55 * - YES: disallow connection
56 *
57 */
58#include "platform.h"
59#include "gnunet-service-transport.h"
60#include "gnunet-service-transport_blacklist.h"
61#include "gnunet-service-transport_neighbours.h"
62#include "transport.h"
63
64/**
65 * Size of the blacklist hash map.
66 */
67#define TRANSPORT_BLACKLIST_HT_SIZE 64
68
69
70/**
71 * Context we use when performing a blacklist check.
72 */
73struct GST_BlacklistCheck;
74
75
76/**
77 * Information kept for each client registered to perform
78 * blacklisting.
79 */
80struct Blacklisters
81{
82 /**
83 * This is a linked list.
84 */
85 struct Blacklisters *next;
86
87 /**
88 * This is a linked list.
89 */
90 struct Blacklisters *prev;
91
92 /**
93 * Client responsible for this entry.
94 */
95 struct GNUNET_SERVER_Client *client;
96
97 /**
98 * Blacklist check that we're currently performing (or NULL
99 * if we're performing one that has been cancelled).
100 */
101 struct GST_BlacklistCheck *bc;
102
103 /**
104 * Set to #GNUNET_YES if we're currently waiting for a reply.
105 */
106 int waiting_for_reply;
107
108 /**
109 * #GNUNET_YES if we have to call receive_done for this client
110 */
111 int call_receive_done;
112
113};
114
115
116
117/**
118 * Context we use when performing a blacklist check.
119 */
120struct GST_BlacklistCheck
121{
122
123 /**
124 * This is a linked list.
125 */
126 struct GST_BlacklistCheck *next;
127
128 /**
129 * This is a linked list.
130 */
131 struct GST_BlacklistCheck *prev;
132
133 /**
134 * Peer being checked.
135 */
136 struct GNUNET_PeerIdentity peer;
137
138 /**
139 * Continuation to call with the result.
140 */
141 GST_BlacklistTestContinuation cont;
142
143 /**
144 * Closure for @e cont.
145 */
146 void *cont_cls;
147
148 /**
149 * Address for #GST_blacklist_abort_matching(), can be NULL.
150 */
151 struct GNUNET_HELLO_Address *address;
152
153 /**
154 * Session for #GST_blacklist_abort_matching(), can be NULL.
155 */
156 struct GNUNET_ATS_Session *session;
157
158 /**
159 * Current transmission request handle for this client, or NULL if no
160 * request is pending.
161 */
162 struct GNUNET_SERVER_TransmitHandle *th;
163
164 /**
165 * Our current position in the blacklisters list.
166 */
167 struct Blacklisters *bl_pos;
168
169 /**
170 * Current task performing the check.
171 */
172 struct GNUNET_SCHEDULER_Task *task;
173
174};
175
176
177/**
178 * Head of DLL of active blacklisting queries.
179 */
180static struct GST_BlacklistCheck *bc_head;
181
182/**
183 * Tail of DLL of active blacklisting queries.
184 */
185static struct GST_BlacklistCheck *bc_tail;
186
187/**
188 * Head of DLL of blacklisting clients.
189 */
190static struct Blacklisters *bl_head;
191
192/**
193 * Tail of DLL of blacklisting clients.
194 */
195static struct Blacklisters *bl_tail;
196
197/**
198 * Hashmap of blacklisted peers. Values are of type 'char *' (transport names),
199 * can be NULL if we have no static blacklist.
200 */
201static struct GNUNET_CONTAINER_MultiPeerMap *blacklist;
202
203
204/**
205 * Perform next action in the blacklist check.
206 *
207 * @param cls the `struct BlacklistCheck*`
208 */
209static void
210do_blacklist_check (void *cls);
211
212
213/**
214 * Called whenever a client is disconnected. Frees our
215 * resources associated with that client.
216 *
217 * @param cls closure (unused)
218 * @param client identification of the client
219 */
220static void
221client_disconnect_notification (void *cls,
222 struct GNUNET_SERVER_Client *client)
223{
224 struct Blacklisters *bl;
225 struct GST_BlacklistCheck *bc;
226
227 if (NULL == client)
228 return;
229 for (bl = bl_head; bl != NULL; bl = bl->next)
230 {
231 if (bl->client != client)
232 continue;
233 for (bc = bc_head; NULL != bc; bc = bc->next)
234 {
235 if (bc->bl_pos != bl)
236 continue;
237 bc->bl_pos = bl->next;
238 if (NULL != bc->th)
239 {
240 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
241 bc->th = NULL;
242 }
243 if (NULL == bc->task)
244 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
245 }
246 GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl);
247 GNUNET_SERVER_client_drop (bl->client);
248 GNUNET_free (bl);
249 break;
250 }
251}
252
253
254/**
255 * Function to iterate over options in the blacklisting section for a peer.
256 *
257 * @param cls closure
258 * @param section name of the section
259 * @param option name of the option
260 * @param value value of the option
261 */
262static void
263blacklist_cfg_iter (void *cls,
264 const char *section,
265 const char *option,
266 const char *value)
267{
268 unsigned int *res = cls;
269 struct GNUNET_PeerIdentity peer;
270 char *plugs;
271 char *pos;
272
273 if (GNUNET_OK !=
274 GNUNET_CRYPTO_eddsa_public_key_from_string (option,
275 strlen (option),
276 &peer.public_key))
277 return;
278
279 if ((NULL == value) || (0 == strcmp(value, "")))
280 {
281 /* Blacklist whole peer */
282 GST_blacklist_add_peer (&peer, NULL);
283 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
284 _("Adding blacklisting entry for peer `%s'\n"),
285 GNUNET_i2s (&peer));
286 }
287 else
288 {
289 plugs = GNUNET_strdup (value);
290 for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " "))
291 {
292 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
293 _("Adding blacklisting entry for peer `%s':`%s'\n"),
294 GNUNET_i2s (&peer), pos);
295 GST_blacklist_add_peer (&peer, pos);
296 }
297 GNUNET_free (plugs);
298 }
299 (*res)++;
300}
301
302
303/**
304 * Read blacklist configuration
305 *
306 * @param cfg the configuration handle
307 * @param my_id my peer identity
308 */
309static void
310read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg,
311 const struct GNUNET_PeerIdentity *my_id)
312{
313 char cfg_sect[512];
314 unsigned int res = 0;
315
316 GNUNET_snprintf (cfg_sect,
317 sizeof (cfg_sect),
318 "transport-blacklist-%s",
319 GNUNET_i2s_full (my_id));
320 GNUNET_CONFIGURATION_iterate_section_values (cfg,
321 cfg_sect,
322 &blacklist_cfg_iter,
323 &res);
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
325 "Loaded %u blacklisting entries from configuration\n",
326 res);
327}
328
329
330/**
331 * Start blacklist subsystem.
332 *
333 * @param server server used to accept clients from
334 * @param cfg configuration handle
335 * @param my_id my peer id
336 */
337void
338GST_blacklist_start (struct GNUNET_SERVER_Handle *server,
339 const struct GNUNET_CONFIGURATION_Handle *cfg,
340 const struct GNUNET_PeerIdentity *my_id)
341{
342 GNUNET_assert (NULL != cfg);
343 GNUNET_assert (NULL != my_id);
344 read_blacklist_configuration (cfg, my_id);
345 GNUNET_SERVER_disconnect_notify (server,
346 &client_disconnect_notification,
347 NULL);
348}
349
350
351/**
352 * Free the given entry in the blacklist.
353 *
354 * @param cls unused
355 * @param key host identity (unused)
356 * @param value the blacklist entry
357 * @return #GNUNET_OK (continue to iterate)
358 */
359static int
360free_blacklist_entry (void *cls,
361 const struct GNUNET_PeerIdentity *key,
362 void *value)
363{
364 char *be = value;
365
366 GNUNET_free_non_null (be);
367 return GNUNET_OK;
368}
369
370
371/**
372 * Stop blacklist subsystem.
373 */
374void
375GST_blacklist_stop ()
376{
377 if (NULL == blacklist)
378 return;
379 GNUNET_CONTAINER_multipeermap_iterate (blacklist,
380 &free_blacklist_entry,
381 NULL);
382 GNUNET_CONTAINER_multipeermap_destroy (blacklist);
383 blacklist = NULL;
384}
385
386
387/**
388 * Transmit blacklist query to the client.
389 *
390 * @param cls the `struct GST_BlacklistCheck`
391 * @param size number of bytes allowed
392 * @param buf where to copy the message
393 * @return number of bytes copied to @a buf
394 */
395static size_t
396transmit_blacklist_message (void *cls,
397 size_t size,
398 void *buf)
399{
400 struct GST_BlacklistCheck *bc = cls;
401 struct Blacklisters *bl;
402 struct BlacklistMessage bm;
403
404 bc->th = NULL;
405 if (0 == size)
406 {
407 GNUNET_assert (NULL == bc->task);
408 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
409 bc);
410 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
411 "Failed to send blacklist test for peer `%s' to client\n",
412 GNUNET_i2s (&bc->peer));
413 return 0;
414 }
415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
416 "Sending blacklist test for peer `%s' to client %p\n",
417 GNUNET_i2s (&bc->peer),
418 bc->bl_pos->client);
419 bl = bc->bl_pos;
420 bm.header.size = htons (sizeof (struct BlacklistMessage));
421 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
422 bm.is_allowed = htonl (0);
423 bm.peer = bc->peer;
424 GNUNET_memcpy (buf,
425 &bm,
426 sizeof (bm));
427 if (GNUNET_YES == bl->call_receive_done)
428 {
429 GNUNET_SERVER_receive_done (bl->client,
430 GNUNET_OK);
431 bl->call_receive_done = GNUNET_NO;
432 }
433
434 bl->waiting_for_reply = GNUNET_YES;
435 return sizeof (bm);
436}
437
438
439/**
440 * Perform next action in the blacklist check.
441 *
442 * @param cls the `struct GST_BlacklistCheck *`
443 */
444static void
445do_blacklist_check (void *cls)
446{
447 struct GST_BlacklistCheck *bc = cls;
448 struct Blacklisters *bl;
449
450 bc->task = NULL;
451 bl = bc->bl_pos;
452 if (NULL == bl)
453 {
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 "No other blacklist clients active, will allow neighbour `%s'\n",
456 GNUNET_i2s (&bc->peer));
457
458 bc->cont (bc->cont_cls,
459 &bc->peer,
460 bc->address,
461 bc->session,
462 GNUNET_OK);
463 GST_blacklist_test_cancel (bc);
464 return;
465 }
466 if ( (NULL != bl->bc) ||
467 (GNUNET_NO != bl->waiting_for_reply) )
468 return; /* someone else busy with this client */
469 bl->bc = bc;
470 bc->th =
471 GNUNET_SERVER_notify_transmit_ready (bl->client,
472 sizeof (struct BlacklistMessage),
473 GNUNET_TIME_UNIT_FOREVER_REL,
474 &transmit_blacklist_message,
475 bc);
476}
477
478
479/**
480 * Got the result about an existing connection from a new blacklister.
481 * Shutdown the neighbour if necessary.
482 *
483 * @param cls unused
484 * @param peer the neighbour that was investigated
485 * @param address address associated with the request
486 * @param session session associated with the request
487 * @param allowed #GNUNET_OK if we can keep it,
488 * #GNUNET_NO if we must shutdown the connection
489 */
490static void
491confirm_or_drop_neighbour (void *cls,
492 const struct GNUNET_PeerIdentity *peer,
493 const struct GNUNET_HELLO_Address *address,
494 struct GNUNET_ATS_Session *session,
495 int allowed)
496{
497 if (GNUNET_OK == allowed)
498 return; /* we're done */
499 GNUNET_STATISTICS_update (GST_stats,
500 gettext_noop ("# disconnects due to blacklist"),
501 1,
502 GNUNET_NO);
503 GST_neighbours_force_disconnect (peer);
504}
505
506
507/**
508 * Closure for #test_connection_ok().
509 */
510struct TestConnectionContext
511{
512 /**
513 * Is this the first neighbour we're checking?
514 */
515 int first;
516
517 /**
518 * Handle to the blacklisting client we need to ask.
519 */
520 struct Blacklisters *bl;
521};
522
523
524/**
525 * Test if an existing connection is still acceptable given a new
526 * blacklisting client.
527 *
528 * @param cls the `struct TestConnectionContext *`
529 * @param peer identity of the peer
530 * @param address the address
531 * @param state current state this peer is in
532 * @param state_timeout timeout for the current state of the peer
533 * @param bandwidth_in bandwidth assigned inbound
534 * @param bandwidth_out bandwidth assigned outbound
535 */
536static void
537test_connection_ok (void *cls,
538 const struct GNUNET_PeerIdentity *peer,
539 const struct GNUNET_HELLO_Address *address,
540 enum GNUNET_TRANSPORT_PeerState state,
541 struct GNUNET_TIME_Absolute state_timeout,
542 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
543 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
544{
545 struct TestConnectionContext *tcc = cls;
546 struct GST_BlacklistCheck *bc;
547
548 bc = GNUNET_new (struct GST_BlacklistCheck);
549 GNUNET_CONTAINER_DLL_insert (bc_head,
550 bc_tail,
551 bc);
552 bc->peer = *peer;
553 bc->address = GNUNET_HELLO_address_copy (address);
554 bc->cont = &confirm_or_drop_neighbour;
555 bc->cont_cls = NULL;
556 bc->bl_pos = tcc->bl;
557 if (GNUNET_YES == tcc->first)
558 {
559 /* all would wait for the same client, no need to
560 * create more than just the first task right now */
561 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
562 tcc->first = GNUNET_NO;
563 }
564}
565
566
567/**
568 * Initialize a blacklisting client. We got a blacklist-init
569 * message from this client, add him to the list of clients
570 * to query for blacklisting.
571 *
572 * @param cls unused
573 * @param client the client
574 * @param message the blacklist-init message that was sent
575 */
576void
577GST_blacklist_handle_init (void *cls,
578 struct GNUNET_SERVER_Client *client,
579 const struct GNUNET_MessageHeader *message)
580{
581 struct Blacklisters *bl;
582 struct TestConnectionContext tcc;
583
584 for (bl = bl_head; NULL != bl; bl = bl->next)
585 if (bl->client == client)
586 {
587 GNUNET_break (0);
588 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
589 return;
590 }
591
592 GNUNET_SERVER_client_mark_monitor (client);
593 bl = GNUNET_new (struct Blacklisters);
594 bl->client = client;
595 bl->call_receive_done = GNUNET_YES;
596 GNUNET_SERVER_client_keep (client);
597 GNUNET_CONTAINER_DLL_insert_after (bl_head,
598 bl_tail,
599 bl_tail,
600 bl);
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
602 "New blacklist client %p\n",
603 client);
604
605 /* confirm that all existing connections are OK! */
606 tcc.bl = bl;
607 tcc.first = GNUNET_YES;
608 GST_neighbours_iterate (&test_connection_ok, &tcc);
609}
610
611
612/**
613 * A blacklisting client has sent us reply. Process it.
614 *
615 * @param cls unused
616 * @param client the client
617 * @param message the blacklist-init message that was sent
618 */
619void
620GST_blacklist_handle_reply (void *cls,
621 struct GNUNET_SERVER_Client *client,
622 const struct GNUNET_MessageHeader *message)
623{
624 const struct BlacklistMessage *msg =
625 (const struct BlacklistMessage *) message;
626 struct Blacklisters *bl;
627 struct GST_BlacklistCheck *bc;
628
629 bl = bl_head;
630 while ((bl != NULL) && (bl->client != client))
631 bl = bl->next;
632 if (NULL == bl)
633 {
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Blacklist client disconnected\n");
636 GNUNET_SERVER_receive_done (client,
637 GNUNET_SYSERR);
638 return;
639 }
640
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642 "Blacklist client %p sent reply for `%s'\n",
643 client,
644 GNUNET_i2s (&msg->peer));
645
646 bc = bl->bc;
647 bl->bc = NULL;
648 bl->waiting_for_reply = GNUNET_NO;
649 bl->call_receive_done = GNUNET_YES; /* Remember to call receive_done */
650 if (NULL != bc)
651 {
652 /* only run this if the blacklist check has not been
653 * cancelled in the meantime... */
654 GNUNET_assert (bc->bl_pos == bl);
655 if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
656 {
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Blacklist check failed, peer not allowed\n");
659 /* For the duration of the continuation, make the ongoing
660 check invisible (to avoid double-cancellation); then
661 add it back again so we can re-use GST_blacklist_test_cancel() */
662 GNUNET_CONTAINER_DLL_remove (bc_head,
663 bc_tail,
664 bc);
665 bc->cont (bc->cont_cls,
666 &bc->peer,
667 bc->address,
668 bc->session,
669 GNUNET_NO);
670 GNUNET_CONTAINER_DLL_insert (bc_head,
671 bc_tail,
672 bc);
673 GST_blacklist_test_cancel (bc);
674 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
675 bl->call_receive_done = GNUNET_NO;
676 return;
677 }
678 else
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 "Blacklist check succeeded, continuing with checks\n");
682 GNUNET_SERVER_receive_done (bl->client,
683 GNUNET_OK);
684 bl->call_receive_done = GNUNET_NO;
685 bc->bl_pos = bl->next;
686 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
687 bc);
688 }
689 }
690 /* check if any other blacklist checks are waiting for this blacklister */
691 for (bc = bc_head; bc != NULL; bc = bc->next)
692 if ((bc->bl_pos == bl) && (NULL == bc->task))
693 {
694 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
695 bc);
696 break;
697 }
698}
699
700
701/**
702 * Add the given peer to the blacklist (for the given transport).
703 *
704 * @param peer peer to blacklist
705 * @param transport_name transport to blacklist for this peer, NULL for all
706 */
707void
708GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
709 const char *transport_name)
710{
711 char *transport = NULL;
712
713 if (NULL != transport_name)
714 {
715 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
716 "Adding peer `%s' with plugin `%s' to blacklist\n",
717 GNUNET_i2s (peer), transport_name);
718 transport = GNUNET_strdup (transport_name);
719 }
720 else
721 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
722 "Adding peer `%s' with all plugins to blacklist\n",
723 GNUNET_i2s (peer));
724 if (NULL == blacklist)
725 blacklist =
726 GNUNET_CONTAINER_multipeermap_create (TRANSPORT_BLACKLIST_HT_SIZE,
727 GNUNET_NO);
728
729 GNUNET_CONTAINER_multipeermap_put (blacklist, peer,
730 transport,
731 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
732}
733
734
735/**
736 * Abort blacklist if @a address and @a session match.
737 *
738 * @param address address used to abort matching checks
739 * @param session session used to abort matching checks
740 */
741void
742GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address,
743 struct GNUNET_ATS_Session *session)
744{
745 struct GST_BlacklistCheck *bc;
746 struct GST_BlacklistCheck *n;
747
748 n = bc_head;
749 while (NULL != (bc = n))
750 {
751 n = bc->next;
752 if ( (bc->session == session) &&
753 (0 == GNUNET_HELLO_address_cmp (bc->address,
754 address)) )
755 {
756 bc->cont (bc->cont_cls,
757 &bc->peer,
758 bc->address,
759 bc->session,
760 GNUNET_SYSERR);
761 GST_blacklist_test_cancel (bc);
762 }
763 }
764}
765
766
767/**
768 * Test if the given blacklist entry matches. If so,
769 * abort the iteration.
770 *
771 * @param cls the transport name to match (const char*)
772 * @param key the key (unused)
773 * @param value the 'char *' (name of a blacklisted transport)
774 * @return #GNUNET_OK if the entry does not match, #GNUNET_NO if it matches
775 */
776static int
777test_blacklisted (void *cls,
778 const struct GNUNET_PeerIdentity *key,
779 void *value)
780{
781 const char *transport_name = cls;
782 char *be = value;
783
784 /* Blacklist entry be:
785 * (NULL == be): peer is blacklisted with all plugins
786 * (NULL != be): peer is blacklisted for a specific plugin
787 *
788 * If (NULL != transport_name) we look for a transport specific entry:
789 * if (transport_name == be) forbidden
790 *
791 */
792
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794 "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n",
795 GNUNET_i2s (key),
796 (NULL == transport_name) ? "unspecified" : transport_name,
797 (NULL == be) ? "all plugins" : be);
798 /* all plugins for this peer were blacklisted: disallow */
799 if (NULL == value)
800 return GNUNET_NO;
801
802 /* blacklist check for specific transport */
803 if ((NULL != transport_name) && (NULL != value))
804 {
805 if (0 == strcmp (transport_name,
806 be))
807 return GNUNET_NO; /* plugin is blacklisted! */
808 }
809 return GNUNET_OK;
810}
811
812
813/**
814 * Test if a peer/transport combination is blacklisted.
815 *
816 * @param peer the identity of the peer to test
817 * @param transport_name name of the transport to test, never NULL
818 * @param cont function to call with result
819 * @param cont_cls closure for @a cont
820 * @param address address to pass back to @a cont, can be NULL
821 * @param session session to pass back to @a cont, can be NULL
822 * @return handle to the blacklist check, NULL if the decision
823 * was made instantly and @a cont was already called
824 */
825struct GST_BlacklistCheck *
826GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
827 const char *transport_name,
828 GST_BlacklistTestContinuation cont,
829 void *cont_cls,
830 const struct GNUNET_HELLO_Address *address,
831 struct GNUNET_ATS_Session *session)
832{
833 struct GST_BlacklistCheck *bc;
834
835 GNUNET_assert (NULL != peer);
836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
837 "Blacklist check for peer `%s':%s\n",
838 GNUNET_i2s (peer),
839 (NULL != transport_name) ? transport_name : "unspecified");
840
841 /* Check local blacklist by iterating over hashmap
842 * If iteration is aborted, we found a matching blacklist entry */
843 if ((NULL != blacklist) &&
844 (GNUNET_SYSERR ==
845 GNUNET_CONTAINER_multipeermap_get_multiple (blacklist, peer,
846 &test_blacklisted,
847 (void *) transport_name)))
848 {
849 /* Disallowed by config, disapprove instantly */
850 GNUNET_STATISTICS_update (GST_stats,
851 gettext_noop ("# disconnects due to blacklist"),
852 1,
853 GNUNET_NO);
854 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
855 _("Disallowing connection to peer `%s' on transport %s\n"),
856 GNUNET_i2s (peer),
857 (NULL != transport_name) ? transport_name : "unspecified");
858 if (NULL != cont)
859 cont (cont_cls,
860 peer,
861 address,
862 session,
863 GNUNET_NO);
864 return NULL;
865 }
866
867 if (NULL == bl_head)
868 {
869 /* no blacklist clients, approve instantly */
870 if (NULL != cont)
871 cont (cont_cls,
872 peer,
873 address,
874 session,
875 GNUNET_OK);
876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
877 "Allowing connection to peer `%s' %s\n",
878 GNUNET_i2s (peer),
879 (NULL != transport_name) ? transport_name : "");
880 return NULL;
881 }
882
883 /* need to query blacklist clients */
884 bc = GNUNET_new (struct GST_BlacklistCheck);
885 GNUNET_CONTAINER_DLL_insert (bc_head,
886 bc_tail,
887 bc);
888 bc->peer = *peer;
889 bc->address = GNUNET_HELLO_address_copy (address);
890 bc->session = session;
891 bc->cont = cont;
892 bc->cont_cls = cont_cls;
893 bc->bl_pos = bl_head;
894 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
895 return bc;
896}
897
898
899/**
900 * Cancel a blacklist check.
901 *
902 * @param bc check to cancel
903 */
904void
905GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc)
906{
907 GNUNET_CONTAINER_DLL_remove (bc_head,
908 bc_tail,
909 bc);
910 if (NULL != bc->bl_pos)
911 {
912 if (bc->bl_pos->bc == bc)
913 {
914 /* we're at the head of the queue, remove us! */
915 bc->bl_pos->bc = NULL;
916 }
917 }
918 if (NULL != bc->task)
919 {
920 GNUNET_SCHEDULER_cancel (bc->task);
921 bc->task = NULL;
922 }
923 if (NULL != bc->th)
924 {
925 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
926 bc->th = NULL;
927 }
928 GNUNET_free_non_null (bc->address);
929 GNUNET_free (bc);
930}
931
932
933/* end of file gnunet-service-transport_blacklist.c */