aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_blacklist.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-04 20:49:35 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-04 20:49:35 +0000
commited4272a244d2770c42ffdb22c80cb4245fbcf538 (patch)
tree5e43c11209a67431bec2e49b2e82da64ab1f0fd0 /src/transport/gnunet-service-transport_blacklist.c
parentb766cf70853e0732c0785648acd74c6958fea5a7 (diff)
downloadgnunet-ed4272a244d2770c42ffdb22c80cb4245fbcf538.tar.gz
gnunet-ed4272a244d2770c42ffdb22c80cb4245fbcf538.zip
implementing blacklist
Diffstat (limited to 'src/transport/gnunet-service-transport_blacklist.c')
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c800
1 files changed, 800 insertions, 0 deletions
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
new file mode 100644
index 000000000..aa4644d10
--- /dev/null
+++ b/src/transport/gnunet-service-transport_blacklist.c
@@ -0,0 +1,800 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file transport/gnunet-service-transport_blacklist.c
23 * @brief blacklisting implementation
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet-service-transport.h"
28#include "gnunet-service-transport_blacklist.h"
29#include "gnunet-service-transport_neighbours.h"
30#include "transport.h"
31
32
33/**
34 * Size of the blacklist hash map.
35 */
36#define TRANSPORT_BLACKLIST_HT_SIZE 64
37
38
39/**
40 * Context we use when performing a blacklist check.
41 */
42struct BlacklistCheck;
43
44
45/**
46 * Information kept for each client registered to perform
47 * blacklisting.
48 */
49struct Blacklisters
50{
51 /**
52 * This is a linked list.
53 */
54 struct Blacklisters *next;
55
56 /**
57 * This is a linked list.
58 */
59 struct Blacklisters *prev;
60
61 /**
62 * Client responsible for this entry.
63 */
64 struct GNUNET_SERVER_Client *client;
65
66 /**
67 * Blacklist check that we're currently performing.
68 */
69 struct BlacklistCheck *bc;
70
71};
72
73
74
75/**
76 * Context we use when performing a blacklist check.
77 */
78struct BlacklistCheck
79{
80
81 /**
82 * This is a linked list.
83 */
84 struct BlacklistCheck *next;
85
86 /**
87 * This is a linked list.
88 */
89 struct BlacklistCheck *prev;
90
91 /**
92 * Peer being checked.
93 */
94 struct GNUNET_PeerIdentity peer;
95
96 /**
97 * Continuation to call with the result.
98 */
99 GST_BlacklistTestContinuation cont;
100
101 /**
102 * Closure for cont.
103 */
104 void *cont_cls;
105
106 /**
107 * Current transmission request handle for this client, or NULL if no
108 * request is pending.
109 */
110 struct GNUNET_CONNECTION_TransmitHandle *th;
111
112 /**
113 * Our current position in the blacklisters list.
114 */
115 struct Blacklisters *bl_pos;
116
117 /**
118 * Current task performing the check.
119 */
120 GNUNET_SCHEDULER_TaskIdentifier task;
121
122};
123
124
125/**
126 * Head of DLL of active blacklisting queries.
127 */
128static struct BlacklistCheck *bc_head;
129
130/**
131 * Tail of DLL of active blacklisting queries.
132 */
133static struct BlacklistCheck *bc_tail;
134
135/**
136 * Head of DLL of blacklisting clients.
137 */
138static struct Blacklisters *bl_head;
139
140/**
141 * Tail of DLL of blacklisting clients.
142 */
143static struct Blacklisters *bl_tail;
144
145/**
146 * Hashmap of blacklisted peers. Values are of type 'char *' (transport names),
147 * can be NULL if we have no static blacklist.
148 */
149static struct GNUNET_CONTAINER_MultiHashMap *blacklist;
150
151
152/**
153 * Perform next action in the blacklist check.
154 *
155 * @param cls the 'struct BlacklistCheck*'
156 * @param tc unused
157 */
158static void
159do_blacklist_check (void *cls,
160 const struct GNUNET_SCHEDULER_TaskContext *tc);
161
162
163/**
164 * Called whenever a client is disconnected. Frees our
165 * resources associated with that client.
166 *
167 * @param cls closure (unused)
168 * @param client identification of the client
169 */
170static void
171client_disconnect_notification (void *cls,
172 struct GNUNET_SERVER_Client *client)
173{
174 struct Blacklisters *bl;
175 struct BlacklistCheck *bc;
176
177 if (client == NULL)
178 return;
179 for (bl = bl_head; bl != NULL; bl = bl->next)
180 {
181 if (bl->client != client)
182 continue;
183 for (bc = bc_head; bc != NULL; bc = bc->next)
184 {
185 if (bc->bl_pos != bl)
186 continue;
187 bc->bl_pos = bl->next;
188 if (bc->th != NULL)
189 {
190 GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
191 bc->th = NULL;
192 }
193 if (bc->task == GNUNET_SCHEDULER_NO_TASK)
194 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
195 bc);
196 break;
197 }
198 GNUNET_CONTAINER_DLL_remove (bl_head,
199 bl_tail,
200 bl);
201 GNUNET_SERVER_client_drop (bl->client);
202 GNUNET_free (bl);
203 break;
204 }
205}
206
207
208/**
209 * Read the blacklist file, containing transport:peer entries.
210 * Provided the transport is loaded, set up hashmap with these
211 * entries to blacklist peers by transport.
212 *
213 */
214static void
215read_blacklist_file ()
216{
217 char *fn;
218 char *data;
219 size_t pos;
220 size_t colon_pos;
221 int tsize;
222 struct GNUNET_PeerIdentity pid;
223 struct stat frstat;
224 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
225 unsigned int entries_found;
226 char *transport_name;
227
228 if (GNUNET_OK !=
229 GNUNET_CONFIGURATION_get_value_filename (GST_cfg,
230 "TRANSPORT",
231 "BLACKLIST_FILE",
232 &fn))
233 {
234#if DEBUG_TRANSPORT
235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
236 "Option `%s' in section `%s' not specified!\n",
237 "BLACKLIST_FILE",
238 "TRANSPORT");
239#endif
240 return;
241 }
242 if (GNUNET_OK != GNUNET_DISK_file_test (fn))
243 GNUNET_DISK_fn_write (fn, NULL, 0,
244 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
245 if (0 != STAT (fn, &frstat))
246 {
247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
248 _("Could not read blacklist file `%s'\n"),
249 fn);
250 GNUNET_free (fn);
251 return;
252 }
253 if (frstat.st_size == 0)
254 {
255#if DEBUG_TRANSPORT
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 _("Blacklist file `%s' is empty.\n"),
258 fn);
259#endif
260 GNUNET_free (fn);
261 return;
262 }
263 /* FIXME: use mmap */
264 data = GNUNET_malloc_large (frstat.st_size);
265 GNUNET_assert(data != NULL);
266 if (frstat.st_size !=
267 GNUNET_DISK_fn_read (fn, data, frstat.st_size))
268 {
269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
270 _("Failed to read blacklist from `%s'\n"),
271 fn);
272 GNUNET_free (fn);
273 GNUNET_free (data);
274 return;
275 }
276 entries_found = 0;
277 pos = 0;
278 while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
279 pos++;
280 while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
281 (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
282 {
283 colon_pos = pos;
284 while ( (colon_pos < frstat.st_size) &&
285 (data[colon_pos] != ':') &&
286 (! isspace ( (unsigned char) data[colon_pos])) )
287 colon_pos++;
288 if (colon_pos >= frstat.st_size)
289 {
290 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
291 _("Syntax error in blacklist file at offset %llu, giving up!\n"),
292 (unsigned long long) colon_pos);
293 GNUNET_free (fn);
294 GNUNET_free (data);
295 return;
296 }
297
298 if (isspace( (unsigned char) data[colon_pos]))
299 {
300 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
301 _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
302 (unsigned long long) colon_pos);
303 pos = colon_pos;
304 while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
305 pos++;
306 continue;
307 }
308 tsize = colon_pos - pos;
309 if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) || (tsize == 0))
310 {
311 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
312 _("Syntax error in blacklist file at offset %llu, giving up!\n"),
313 (unsigned long long) colon_pos);
314 GNUNET_free (fn);
315 GNUNET_free (data);
316 return;
317 }
318
319 if (tsize < 1)
320 continue;
321
322 transport_name = GNUNET_malloc(tsize + 1);
323 memcpy(transport_name, &data[pos], tsize);
324 pos = colon_pos + 1;
325#if DEBUG_TRANSPORT
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327 "Read transport name `%s' in blacklist file.\n",
328 transport_name);
329#endif
330 memcpy (&enc,
331 &data[pos],
332 sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
333 if (! isspace ( (unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
336 _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
337 (unsigned long long) pos);
338 pos++;
339 while ((pos < frstat.st_size) && (!isspace ( (unsigned char) data[pos])))
340 pos++;
341 GNUNET_free_non_null(transport_name);
342 continue;
343 }
344 enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
345 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
348 _("Syntax error in blacklist file at offset %llu, skipping bytes `%s'.\n"),
349 (unsigned long long) pos,
350 &enc);
351 }
352 else
353 {
354 if (0 != memcmp (&pid,
355 &GST_my_identity,
356 sizeof (struct GNUNET_PeerIdentity)))
357 {
358 entries_found++;
359 GST_blacklist_add_peer (&pid,
360 transport_name);
361 }
362 else
363 {
364 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
365 _("Found myself `%s' in blacklist (useless, ignored)\n"),
366 GNUNET_i2s (&pid));
367 }
368 }
369 pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
370 GNUNET_free_non_null(transport_name);
371 while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
372 pos++;
373 }
374 GNUNET_STATISTICS_update (GST_stats,
375 "# Transport entries blacklisted",
376 entries_found,
377 GNUNET_NO);
378 GNUNET_free (data);
379 GNUNET_free (fn);
380}
381
382
383/**
384 * Start blacklist subsystem.
385 *
386 * @param server server used to accept clients from
387 */
388void
389GST_blacklist_start (struct GNUNET_SERVER_Handle *server)
390{
391 read_blacklist_file ();
392 GNUNET_SERVER_disconnect_notify (server,
393 &client_disconnect_notification,
394 NULL);
395}
396
397
398/**
399 * Free the given entry in the blacklist.
400 *
401 * @param cls unused
402 * @param key host identity (unused)
403 * @param value the blacklist entry
404 * @return GNUNET_OK (continue to iterate)
405 */
406static int
407free_blacklist_entry (void *cls,
408 const GNUNET_HashCode *key,
409 void *value)
410{
411 char *be = value;
412
413 GNUNET_free (be);
414 return GNUNET_OK;
415}
416
417
418/**
419 * Stop blacklist subsystem.
420 */
421void
422GST_blacklist_stop ()
423{
424 if (NULL != blacklist)
425 {
426 GNUNET_CONTAINER_multihashmap_iterate (blacklist,
427 &free_blacklist_entry,
428 NULL);
429 GNUNET_CONTAINER_multihashmap_destroy (blacklist);
430 blacklist = NULL;
431 }
432}
433
434
435/**
436 * Transmit blacklist query to the client.
437 *
438 * @param cls the 'struct BlacklistCheck'
439 * @param size number of bytes allowed
440 * @param buf where to copy the message
441 * @return number of bytes copied to buf
442 */
443static size_t
444transmit_blacklist_message (void *cls,
445 size_t size,
446 void *buf)
447{
448 struct BlacklistCheck *bc = cls;
449 struct Blacklisters *bl;
450 struct BlacklistMessage bm;
451
452 bc->th = NULL;
453 if (size == 0)
454 {
455 GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK);
456 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
457 bc);
458 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
459 "Failed to send blacklist test for peer `%s' to client\n",
460 GNUNET_i2s (&bc->peer));
461 return 0;
462 }
463#if DEBUG_TRANSPORT
464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465 "Sending blacklist test for peer `%s' to client\n",
466 GNUNET_i2s (&bc->peer));
467#endif
468 bl = bc->bl_pos;
469 bm.header.size = htons (sizeof (struct BlacklistMessage));
470 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
471 bm.is_allowed = htonl (0);
472 bm.peer = bc->peer;
473 memcpy (buf, &bm, sizeof (bm));
474 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
475 return sizeof (bm);
476}
477
478
479/**
480 * Perform next action in the blacklist check.
481 *
482 * @param cls the 'struct BlacklistCheck*'
483 * @param tc unused
484 */
485static void
486do_blacklist_check (void *cls,
487 const struct GNUNET_SCHEDULER_TaskContext *tc)
488{
489 struct BlacklistCheck *bc = cls;
490 struct Blacklisters *bl;
491
492 bc->task = GNUNET_SCHEDULER_NO_TASK;
493 bl = bc->bl_pos;
494 if (bl == NULL)
495 {
496#if DEBUG_TRANSPORT
497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498 "No other blacklist clients active, will allow neighbour `%s'\n",
499 GNUNET_i2s (&bc->peer));
500#endif
501 bc->cont (bc->cont_cls,
502 &bc->peer,
503 GNUNET_OK);
504 GNUNET_free (bc);
505 return;
506 }
507 if (bl->bc != NULL)
508 return; /* someone else busy with this client */
509 bl->bc = bc;
510 bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client,
511 sizeof (struct BlacklistMessage),
512 GNUNET_TIME_UNIT_FOREVER_REL,
513 &transmit_blacklist_message,
514 bc);
515}
516
517
518/**
519 * Got the result about an existing connection from a new blacklister.
520 * Shutdown the neighbour if necessary.
521 *
522 * @param cls unused
523 * @param peer the neighbour that was investigated
524 * @param allowed GNUNET_OK if we can keep it,
525 * GNUNET_NO if we must shutdown the connection
526 */
527static void
528confirm_or_drop_neighbour (void *cls,
529 const struct GNUNET_PeerIdentity *peer,
530 int allowed)
531{
532 if (GNUNET_OK == allowed)
533 return; /* we're done */
534 GNUNET_STATISTICS_update (GST_stats,
535 gettext_noop ("# disconnects due to blacklist"),
536 1,
537 GNUNET_NO);
538 GST_neighbours_force_disconnect (peer);
539}
540
541
542/**
543 * Closure for 'test_connection_ok'.
544 */
545struct TestConnectionContext
546{
547 /**
548 * Is this the first neighbour we're checking?
549 */
550 int first;
551
552 /**
553 * Handle to the blacklisting client we need to ask.
554 */
555 struct Blacklisters *bl;
556};
557
558
559/**
560 * Test if an existing connection is still acceptable given a new
561 * blacklisting client.
562 *
563 * @param cls the 'struct TestConnectionContest'
564 * @param pid neighbour's identity
565 */
566static void
567test_connection_ok (void *cls,
568 const struct GNUNET_PeerIdentity *neighbour)
569{
570 struct TestConnectionContext *tcc = cls;
571 struct BlacklistCheck *bc;
572
573 bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
574 GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
575 bc->peer = *neighbour;
576 bc->cont = &confirm_or_drop_neighbour;
577 bc->cont_cls = NULL;
578 bc->bl_pos = tcc->bl;
579 if (GNUNET_YES == tcc->first)
580 {
581 /* all would wait for the same client, no need to
582 create more than just the first task right now */
583 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
584 bc);
585 tcc->first = GNUNET_NO;
586 }
587}
588
589
590
591/**
592 * Initialize a blacklisting client. We got a blacklist-init
593 * message from this client, add him to the list of clients
594 * to query for blacklisting.
595 *
596 * @param cls unused
597 * @param client the client
598 * @param message the blacklist-init message that was sent
599 */
600void
601GST_blacklist_handle_init (void *cls,
602 struct GNUNET_SERVER_Client *client,
603 const struct GNUNET_MessageHeader *message)
604{
605 struct Blacklisters *bl;
606 struct TestConnectionContext tcc;
607
608 bl = bl_head;
609 while (bl != NULL)
610 {
611 if (bl->client == client)
612 {
613 GNUNET_break (0);
614 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
615 return;
616 }
617 bl = bl->next;
618 }
619 bl = GNUNET_malloc (sizeof (struct Blacklisters));
620 bl->client = client;
621 GNUNET_SERVER_client_keep (client);
622 GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
623
624 /* confirm that all existing connections are OK! */
625 tcc.bl = bl;
626 tcc.first = GNUNET_YES;
627 GST_neighbours_iterate (&test_connection_ok,
628 &tcc);
629}
630
631
632/**
633 * A blacklisting client has sent us reply. Process it.
634 *
635 * @param cls unused
636 * @param client the client
637 * @param message the blacklist-init message that was sent
638 */
639void
640GST_blacklist_handle_reply (void *cls,
641 struct GNUNET_SERVER_Client *client,
642 const struct GNUNET_MessageHeader *message)
643{
644 const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
645 struct Blacklisters *bl;
646 struct BlacklistCheck *bc;
647
648 bl = bl_head;
649 while ( (bl != NULL) &&
650 (bl->client != client) )
651 bl = bl->next;
652 if (bl == NULL)
653 {
654#if DEBUG_TRANSPORT
655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
656 "Blacklist client disconnected\n");
657#endif
658 /* FIXME: other error handling here!? */
659 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
660 return;
661 }
662 bc = bl->bc;
663 bl->bc = NULL;
664 if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
665 {
666#if DEBUG_TRANSPORT
667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668 "Blacklist check failed, peer not allowed\n");
669#endif
670 bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO);
671 GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
672 GNUNET_free (bc);
673 }
674 else
675 {
676#if DEBUG_TRANSPORT
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Blacklist check succeeded, continuing with checks\n");
679#endif
680 bc->bl_pos = bc->bl_pos->next;
681 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
682 bc);
683 }
684 /* check if any other bc's are waiting for this blacklister */
685 bc = bc_head;
686 while (bc != NULL)
687 {
688 if ( (bc->bl_pos == bl) &&
689 (GNUNET_SCHEDULER_NO_TASK == bc->task) )
690 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
691 bc);
692 bc = bc->next;
693 }
694}
695
696
697/**
698 * Add the given peer to the blacklist (for the given transport).
699 *
700 * @param peer peer to blacklist
701 * @param transport_name transport to blacklist for this peer, NULL for all
702 */
703void
704GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
705 const char *transport_name)
706{
707#if DEBUG_TRANSPORT
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "Adding peer `%s' with plugin `%s' to blacklist\n",
710 GNUNET_i2s (peer),
711 transport_name);
712#endif
713 if (blacklist == NULL)
714 blacklist = GNUNET_CONTAINER_multihashmap_create(TRANSPORT_BLACKLIST_HT_SIZE);
715 GNUNET_CONTAINER_multihashmap_put (blacklist,
716 &peer->hashPubKey,
717 GNUNET_strdup (transport_name),
718 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
719}
720
721
722/**
723 * Test if the given blacklist entry matches. If so,
724 * abort the iteration.
725 *
726 * @param cls the transport name to match (const char*)
727 * @param key the key (unused)
728 * @param value the 'char *' (name of a blacklisted transport)
729 * @return GNUNET_OK if the entry does not match, GNUNET_NO if it matches
730 */
731static int
732test_blacklisted (void *cls,
733 const GNUNET_HashCode *key,
734 void *value)
735{
736 const char *transport_name = cls;
737 char *be = value;
738
739 if (0 == strcmp (transport_name,
740 be))
741 return GNUNET_NO; /* abort iteration! */
742 return GNUNET_OK;
743}
744
745
746/**
747 * Test if a peer/transport combination is blacklisted.
748 *
749 * @param peer the identity of the peer to test
750 * @param transport_name name of the transport to test, never NULL
751 * @param cont function to call with result
752 * @param cont_cls closure for 'cont'
753 */
754void
755GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
756 const char *transport_name,
757 GST_BlacklistTestContinuation cont,
758 void *cont_cls)
759{
760 struct BlacklistCheck *bc;
761
762 if ( (blacklist != NULL) &&
763 (GNUNET_SYSERR ==
764 GNUNET_CONTAINER_multihashmap_get_multiple (blacklist,
765 &peer->hashPubKey,
766 &test_blacklisted,
767 (void*) transport_name)) )
768 {
769 /* disallowed by config, disapprove instantly */
770 GNUNET_STATISTICS_update (GST_stats,
771 gettext_noop ("# disconnects due to blacklist"),
772 1,
773 GNUNET_NO);
774 if (cont != NULL)
775 cont (cont_cls, peer, GNUNET_NO);
776 return;
777 }
778
779 if (bl_head == NULL)
780 {
781 /* no blacklist clients, approve instantly */
782 if (cont != NULL)
783 cont (cont_cls, peer, GNUNET_OK);
784 return;
785 }
786
787 /* need to query blacklist clients */
788 bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
789 GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
790 bc->peer = *peer;
791 bc->cont = cont;
792 bc->cont_cls = cont_cls;
793 bc->bl_pos = bl_head;
794 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
795 bc);
796}
797
798
799
800/* end of file gnunet-service-transport_blacklist.c */