aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_blacklist.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-02-18 14:08:39 +0000
committerChristian Grothoff <christian@grothoff.org>2015-02-18 14:08:39 +0000
commit8bd00cee8c4335f9598ef6e97a06736c925862a7 (patch)
tree657258e0b9f88de9a81dfda64dc6629f3a0d370b /src/transport/gnunet-service-transport_blacklist.c
parent060807231ea955a26c481700811dc265908a3138 (diff)
downloadgnunet-8bd00cee8c4335f9598ef6e97a06736c925862a7.tar.gz
gnunet-8bd00cee8c4335f9598ef6e97a06736c925862a7.zip
fix blacklist checking logic, integrating tracking of sessions with blacklist module and fixing dangling session issue which caused misc. problems when blacklists were in use
Diffstat (limited to 'src/transport/gnunet-service-transport_blacklist.c')
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c182
1 files changed, 141 insertions, 41 deletions
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
index 195e3439f..22d62570a 100644
--- a/src/transport/gnunet-service-transport_blacklist.c
+++ b/src/transport/gnunet-service-transport_blacklist.c
@@ -146,6 +146,16 @@ struct GST_BlacklistCheck
146 void *cont_cls; 146 void *cont_cls;
147 147
148 /** 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 Session *session;
157
158 /**
149 * Current transmission request handle for this client, or NULL if no 159 * Current transmission request handle for this client, or NULL if no
150 * request is pending. 160 * request is pending.
151 */ 161 */
@@ -159,7 +169,7 @@ struct GST_BlacklistCheck
159 /** 169 /**
160 * Current task performing the check. 170 * Current task performing the check.
161 */ 171 */
162 struct GNUNET_SCHEDULER_Task * task; 172 struct GNUNET_SCHEDULER_Task *task;
163 173
164}; 174};
165 175
@@ -198,7 +208,8 @@ static struct GNUNET_CONTAINER_MultiPeerMap *blacklist;
198 * @param tc unused 208 * @param tc unused
199 */ 209 */
200static void 210static void
201do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 211do_blacklist_check (void *cls,
212 const struct GNUNET_SCHEDULER_TaskContext *tc);
202 213
203 214
204/** 215/**
@@ -209,7 +220,8 @@ do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
209 * @param client identification of the client 220 * @param client identification of the client
210 */ 221 */
211static void 222static void
212client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) 223client_disconnect_notification (void *cls,
224 struct GNUNET_SERVER_Client *client)
213{ 225{
214 struct Blacklisters *bl; 226 struct Blacklisters *bl;
215 struct GST_BlacklistCheck *bc; 227 struct GST_BlacklistCheck *bc;
@@ -220,17 +232,17 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
220 { 232 {
221 if (bl->client != client) 233 if (bl->client != client)
222 continue; 234 continue;
223 for (bc = bc_head; bc != NULL; bc = bc->next) 235 for (bc = bc_head; NULL != bc; bc = bc->next)
224 { 236 {
225 if (bc->bl_pos != bl) 237 if (bc->bl_pos != bl)
226 continue; 238 continue;
227 bc->bl_pos = bl->next; 239 bc->bl_pos = bl->next;
228 if (bc->th != NULL) 240 if (NULL != bc->th)
229 { 241 {
230 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); 242 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
231 bc->th = NULL; 243 bc->th = NULL;
232 } 244 }
233 if (bc->task == NULL) 245 if (NULL == bc->task)
234 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); 246 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
235 } 247 }
236 GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl); 248 GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl);
@@ -383,17 +395,20 @@ GST_blacklist_stop ()
383 * @return number of bytes copied to @a buf 395 * @return number of bytes copied to @a buf
384 */ 396 */
385static size_t 397static size_t
386transmit_blacklist_message (void *cls, size_t size, void *buf) 398transmit_blacklist_message (void *cls,
399 size_t size,
400 void *buf)
387{ 401{
388 struct GST_BlacklistCheck *bc = cls; 402 struct GST_BlacklistCheck *bc = cls;
389 struct Blacklisters *bl; 403 struct Blacklisters *bl;
390 struct BlacklistMessage bm; 404 struct BlacklistMessage bm;
391 405
392 bc->th = NULL; 406 bc->th = NULL;
393 if (size == 0) 407 if (0 == size)
394 { 408 {
395 GNUNET_assert (bc->task == NULL); 409 GNUNET_assert (NULL == bc->task);
396 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); 410 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
411 bc);
397 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 412 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
398 "Failed to send blacklist test for peer `%s' to client\n", 413 "Failed to send blacklist test for peer `%s' to client\n",
399 GNUNET_i2s (&bc->peer)); 414 GNUNET_i2s (&bc->peer));
@@ -401,16 +416,20 @@ transmit_blacklist_message (void *cls, size_t size, void *buf)
401 } 416 }
402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
403 "Sending blacklist test for peer `%s' to client %p\n", 418 "Sending blacklist test for peer `%s' to client %p\n",
404 GNUNET_i2s (&bc->peer), bc->bl_pos->client); 419 GNUNET_i2s (&bc->peer),
420 bc->bl_pos->client);
405 bl = bc->bl_pos; 421 bl = bc->bl_pos;
406 bm.header.size = htons (sizeof (struct BlacklistMessage)); 422 bm.header.size = htons (sizeof (struct BlacklistMessage));
407 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); 423 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
408 bm.is_allowed = htonl (0); 424 bm.is_allowed = htonl (0);
409 bm.peer = bc->peer; 425 bm.peer = bc->peer;
410 memcpy (buf, &bm, sizeof (bm)); 426 memcpy (buf,
427 &bm,
428 sizeof (bm));
411 if (GNUNET_YES == bl->call_receive_done) 429 if (GNUNET_YES == bl->call_receive_done)
412 { 430 {
413 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); 431 GNUNET_SERVER_receive_done (bl->client,
432 GNUNET_OK);
414 bl->call_receive_done = GNUNET_NO; 433 bl->call_receive_done = GNUNET_NO;
415 } 434 }
416 435
@@ -434,25 +453,30 @@ do_blacklist_check (void *cls,
434 453
435 bc->task = NULL; 454 bc->task = NULL;
436 bl = bc->bl_pos; 455 bl = bc->bl_pos;
437 if (bl == NULL) 456 if (NULL == bl)
438 { 457 {
439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
440 "No other blacklist clients active, will allow neighbour `%s'\n", 459 "No other blacklist clients active, will allow neighbour `%s'\n",
441 GNUNET_i2s (&bc->peer)); 460 GNUNET_i2s (&bc->peer));
442 461
443 bc->cont (bc->cont_cls, &bc->peer, GNUNET_OK); 462 bc->cont (bc->cont_cls,
444 GNUNET_CONTAINER_DLL_remove(bc_head, bc_tail, bc); 463 &bc->peer,
445 GNUNET_free (bc); 464 bc->address,
465 bc->session,
466 GNUNET_OK);
467 GST_blacklist_test_cancel (bc);
446 return; 468 return;
447 } 469 }
448 if ((bl->bc != NULL) || (bl->waiting_for_reply != GNUNET_NO)) 470 if ( (NULL != bl->bc) ||
471 (GNUNET_NO != bl->waiting_for_reply) )
449 return; /* someone else busy with this client */ 472 return; /* someone else busy with this client */
450 bl->bc = bc; 473 bl->bc = bc;
451 bc->th = 474 bc->th =
452 GNUNET_SERVER_notify_transmit_ready (bl->client, 475 GNUNET_SERVER_notify_transmit_ready (bl->client,
453 sizeof (struct BlacklistMessage), 476 sizeof (struct BlacklistMessage),
454 GNUNET_TIME_UNIT_FOREVER_REL, 477 GNUNET_TIME_UNIT_FOREVER_REL,
455 &transmit_blacklist_message, bc); 478 &transmit_blacklist_message,
479 bc);
456} 480}
457 481
458 482
@@ -462,25 +486,30 @@ do_blacklist_check (void *cls,
462 * 486 *
463 * @param cls unused 487 * @param cls unused
464 * @param peer the neighbour that was investigated 488 * @param peer the neighbour that was investigated
489 * @param address address associated with the request
490 * @param session session associated with the request
465 * @param allowed #GNUNET_OK if we can keep it, 491 * @param allowed #GNUNET_OK if we can keep it,
466 * #GNUNET_NO if we must shutdown the connection 492 * #GNUNET_NO if we must shutdown the connection
467 */ 493 */
468static void 494static void
469confirm_or_drop_neighbour (void *cls, 495confirm_or_drop_neighbour (void *cls,
470 const struct GNUNET_PeerIdentity *peer, 496 const struct GNUNET_PeerIdentity *peer,
497 const struct GNUNET_HELLO_Address *address,
498 struct Session *session,
471 int allowed) 499 int allowed)
472{ 500{
473 if (GNUNET_OK == allowed) 501 if (GNUNET_OK == allowed)
474 return; /* we're done */ 502 return; /* we're done */
475 GNUNET_STATISTICS_update (GST_stats, 503 GNUNET_STATISTICS_update (GST_stats,
476 gettext_noop ("# disconnects due to blacklist"), 1, 504 gettext_noop ("# disconnects due to blacklist"),
505 1,
477 GNUNET_NO); 506 GNUNET_NO);
478 GST_neighbours_force_disconnect (peer); 507 GST_neighbours_force_disconnect (peer);
479} 508}
480 509
481 510
482/** 511/**
483 * Closure for 'test_connection_ok'. 512 * Closure for #test_connection_ok().
484 */ 513 */
485struct TestConnectionContext 514struct TestConnectionContext
486{ 515{
@@ -525,6 +554,7 @@ test_connection_ok (void *cls,
525 bc_tail, 554 bc_tail,
526 bc); 555 bc);
527 bc->peer = *peer; 556 bc->peer = *peer;
557 bc->address = GNUNET_HELLO_address_copy (address);
528 bc->cont = &confirm_or_drop_neighbour; 558 bc->cont = &confirm_or_drop_neighbour;
529 bc->cont_cls = NULL; 559 bc->cont_cls = NULL;
530 bc->bl_pos = tcc->bl; 560 bc->bl_pos = tcc->bl;
@@ -548,7 +578,8 @@ test_connection_ok (void *cls,
548 * @param message the blacklist-init message that was sent 578 * @param message the blacklist-init message that was sent
549 */ 579 */
550void 580void
551GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client, 581GST_blacklist_handle_init (void *cls,
582 struct GNUNET_SERVER_Client *client,
552 const struct GNUNET_MessageHeader *message) 583 const struct GNUNET_MessageHeader *message)
553{ 584{
554 struct Blacklisters *bl; 585 struct Blacklisters *bl;
@@ -590,7 +621,8 @@ GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client,
590 * @param message the blacklist-init message that was sent 621 * @param message the blacklist-init message that was sent
591 */ 622 */
592void 623void
593GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client, 624GST_blacklist_handle_reply (void *cls,
625 struct GNUNET_SERVER_Client *client,
594 const struct GNUNET_MessageHeader *message) 626 const struct GNUNET_MessageHeader *message)
595{ 627{
596 const struct BlacklistMessage *msg = 628 const struct BlacklistMessage *msg =
@@ -605,14 +637,15 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
605 { 637 {
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607 "Blacklist client disconnected\n"); 639 "Blacklist client disconnected\n");
608 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 640 GNUNET_SERVER_receive_done (client,
641 GNUNET_SYSERR);
609 return; 642 return;
610 } 643 }
611 644
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
613 "Blacklist client %p sent reply for `%s'\n", 646 "Blacklist client %p sent reply for `%s'\n",
614 client, 647 client,
615 GNUNET_i2s(&msg->peer)); 648 GNUNET_i2s (&msg->peer));
616 649
617 bc = bl->bc; 650 bc = bl->bc;
618 bl->bc = NULL; 651 bl->bc = NULL;
@@ -622,32 +655,48 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
622 { 655 {
623 /* only run this if the blacklist check has not been 656 /* only run this if the blacklist check has not been
624 * cancelled in the meantime... */ 657 * cancelled in the meantime... */
658 GNUNET_assert (bc->bl_pos == bl);
625 if (ntohl (msg->is_allowed) == GNUNET_SYSERR) 659 if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
626 { 660 {
627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
628 "Blacklist check failed, peer not allowed\n"); 662 "Blacklist check failed, peer not allowed\n");
629 bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO); 663 /* For the duration of the continuation, make the ongoing
630 GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); 664 check invisible (to avoid double-cancellation); then
665 add it back again so we can re-use GST_blacklist_test_cancel() */
666 GNUNET_CONTAINER_DLL_remove (bc_head,
667 bc_tail,
668 bc);
669 bc->cont (bc->cont_cls,
670 &bc->peer,
671 bc->address,
672 bc->session,
673 GNUNET_NO);
674 GNUNET_CONTAINER_DLL_insert (bc_head,
675 bc_tail,
676 bc);
677 GST_blacklist_test_cancel (bc);
631 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); 678 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
632 bl->call_receive_done = GNUNET_NO; 679 bl->call_receive_done = GNUNET_NO;
633 GNUNET_free (bc);
634 return; 680 return;
635 } 681 }
636 else 682 else
637 { 683 {
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639 "Blacklist check succeeded, continuing with checks\n"); 685 "Blacklist check succeeded, continuing with checks\n");
640 GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); 686 GNUNET_SERVER_receive_done (bl->client,
687 GNUNET_OK);
641 bl->call_receive_done = GNUNET_NO; 688 bl->call_receive_done = GNUNET_NO;
642 bc->bl_pos = bc->bl_pos->next; 689 bc->bl_pos = bl->next;
643 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); 690 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
691 bc);
644 } 692 }
645 } 693 }
646 /* check if any other blacklist checks are waiting for this blacklister */ 694 /* check if any other blacklist checks are waiting for this blacklister */
647 for (bc = bc_head; bc != NULL; bc = bc->next) 695 for (bc = bc_head; bc != NULL; bc = bc->next)
648 if ((bc->bl_pos == bl) && (NULL == bc->task)) 696 if ((bc->bl_pos == bl) && (NULL == bc->task))
649 { 697 {
650 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); 698 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
699 bc);
651 break; 700 break;
652 } 701 }
653} 702}
@@ -688,6 +737,38 @@ GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
688 737
689 738
690/** 739/**
740 * Abort blacklist if @a address and @a session match.
741 *
742 * @param address address used to abort matching checks
743 * @param session session used to abort matching checks
744 */
745void
746GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address,
747 struct Session *session)
748{
749 struct GST_BlacklistCheck *bc;
750 struct GST_BlacklistCheck *n;
751
752 n = bc_head;
753 while (NULL != (bc = n))
754 {
755 n = bc->next;
756 if ( (bc->session == session) &&
757 (0 == GNUNET_HELLO_address_cmp (bc->address,
758 address)) )
759 {
760 bc->cont (bc->cont_cls,
761 &bc->peer,
762 bc->address,
763 bc->session,
764 GNUNET_SYSERR);
765 GST_blacklist_test_cancel (bc);
766 }
767 }
768}
769
770
771/**
691 * Test if the given blacklist entry matches. If so, 772 * Test if the given blacklist entry matches. If so,
692 * abort the iteration. 773 * abort the iteration.
693 * 774 *
@@ -725,8 +806,9 @@ test_blacklisted (void *cls,
725 /* blacklist check for specific transport */ 806 /* blacklist check for specific transport */
726 if ((NULL != transport_name) && (NULL != value)) 807 if ((NULL != transport_name) && (NULL != value))
727 { 808 {
728 if (0 == strcmp (transport_name, be)) 809 if (0 == strcmp (transport_name,
729 return GNUNET_NO; /* plugin is blacklisted! */ 810 be))
811 return GNUNET_NO; /* plugin is blacklisted! */
730 } 812 }
731 return GNUNET_OK; 813 return GNUNET_OK;
732} 814}
@@ -739,6 +821,8 @@ test_blacklisted (void *cls,
739 * @param transport_name name of the transport to test, never NULL 821 * @param transport_name name of the transport to test, never NULL
740 * @param cont function to call with result 822 * @param cont function to call with result
741 * @param cont_cls closure for @a cont 823 * @param cont_cls closure for @a cont
824 * @param address address to pass back to @a cont, can be NULL
825 * @param session session to pass back to @a cont, can be NULL
742 * @return handle to the blacklist check, NULL if the decision 826 * @return handle to the blacklist check, NULL if the decision
743 * was made instantly and @a cont was already called 827 * was made instantly and @a cont was already called
744 */ 828 */
@@ -746,7 +830,9 @@ struct GST_BlacklistCheck *
746GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, 830GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
747 const char *transport_name, 831 const char *transport_name,
748 GST_BlacklistTestContinuation cont, 832 GST_BlacklistTestContinuation cont,
749 void *cont_cls) 833 void *cont_cls,
834 const struct GNUNET_HELLO_Address *address,
835 struct Session *session)
750{ 836{
751 struct GST_BlacklistCheck *bc; 837 struct GST_BlacklistCheck *bc;
752 838
@@ -767,21 +853,30 @@ GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
767 /* Disallowed by config, disapprove instantly */ 853 /* Disallowed by config, disapprove instantly */
768 GNUNET_STATISTICS_update (GST_stats, 854 GNUNET_STATISTICS_update (GST_stats,
769 gettext_noop ("# disconnects due to blacklist"), 855 gettext_noop ("# disconnects due to blacklist"),
770 1, GNUNET_NO); 856 1,
857 GNUNET_NO);
771 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 858 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
772 _("Disallowing connection to peer `%s' on transport %s\n"), 859 _("Disallowing connection to peer `%s' on transport %s\n"),
773 GNUNET_i2s (peer), 860 GNUNET_i2s (peer),
774 (NULL != transport_name) ? transport_name : "unspecified"); 861 (NULL != transport_name) ? transport_name : "unspecified");
775 if (cont != NULL) 862 if (NULL != cont)
776 cont (cont_cls, peer, GNUNET_NO); 863 cont (cont_cls,
864 peer,
865 address,
866 session,
867 GNUNET_NO);
777 return NULL; 868 return NULL;
778 } 869 }
779 870
780 if (NULL == bl_head) 871 if (NULL == bl_head)
781 { 872 {
782 /* no blacklist clients, approve instantly */ 873 /* no blacklist clients, approve instantly */
783 if (cont != NULL) 874 if (NULL != cont)
784 cont (cont_cls, peer, GNUNET_OK); 875 cont (cont_cls,
876 peer,
877 address,
878 session,
879 GNUNET_OK);
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 "Allowing connection to peer `%s' %s\n", 881 "Allowing connection to peer `%s' %s\n",
787 GNUNET_i2s (peer), 882 GNUNET_i2s (peer),
@@ -791,8 +886,12 @@ GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
791 886
792 /* need to query blacklist clients */ 887 /* need to query blacklist clients */
793 bc = GNUNET_new (struct GST_BlacklistCheck); 888 bc = GNUNET_new (struct GST_BlacklistCheck);
794 GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); 889 GNUNET_CONTAINER_DLL_insert (bc_head,
890 bc_tail,
891 bc);
795 bc->peer = *peer; 892 bc->peer = *peer;
893 bc->address = GNUNET_HELLO_address_copy (address);
894 bc->session = session;
796 bc->cont = cont; 895 bc->cont = cont;
797 bc->cont_cls = cont_cls; 896 bc->cont_cls = cont_cls;
798 bc->bl_pos = bl_head; 897 bc->bl_pos = bl_head;
@@ -830,6 +929,7 @@ GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc)
830 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); 929 GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
831 bc->th = NULL; 930 bc->th = NULL;
832 } 931 }
932 GNUNET_free_non_null (bc->address);
833 GNUNET_free (bc); 933 GNUNET_free (bc);
834} 934}
835 935