aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-21 08:14:23 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-21 08:14:23 +0000
commitb6818796397f2a15992ce759a0005dc848e19e23 (patch)
tree4d5a957253497cf3d9bda00751f08570bea88907 /src/transport
parent6f7541fa5956928c2b8ec10aa075e2aac12c3235 (diff)
downloadgnunet-b6818796397f2a15992ce759a0005dc848e19e23.tar.gz
gnunet-b6818796397f2a15992ce759a0005dc848e19e23.zip
towards implementing blacklisting
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/gnunet-service-transport.c320
1 files changed, 226 insertions, 94 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index a30595d02..7396d0ca3 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -67,6 +67,11 @@
67#define MAX_PENDING 128 67#define MAX_PENDING 128
68 68
69/** 69/**
70 * Size of the per-transport blacklist hash maps.
71 */
72#define TRANSPORT_BLACKLIST_HT_SIZE 16
73
74/**
70 * How often should we try to reconnect to a peer using a particular 75 * How often should we try to reconnect to a peer using a particular
71 * transport plugin before giving up? Note that the plugin may be 76 * transport plugin before giving up? Note that the plugin may be
72 * added back to the list after PLUGIN_RETRY_FREQUENCY expires. 77 * added back to the list after PLUGIN_RETRY_FREQUENCY expires.
@@ -944,26 +949,24 @@ is_blacklisted (const struct GNUNET_PeerIdentity *peer, struct TransportPlugin *
944 return GNUNET_NO; 949 return GNUNET_NO;
945} 950}
946 951
952
947static void 953static void
948add_peer_to_blacklist (struct GNUNET_PeerIdentity *peer, char *transport_name) 954add_peer_to_blacklist (struct GNUNET_PeerIdentity *peer, char *transport_name)
949{ 955{
950 struct TransportPlugin *plugin; 956 struct TransportPlugin *plugin;
951 957
952 plugin = find_transport(transport_name); 958 plugin = find_transport(transport_name);
953
954 if (plugin == NULL) /* Nothing to do */ 959 if (plugin == NULL) /* Nothing to do */
955 return; 960 return;
956 961 if (plugin->blacklist == NULL)
957 if (plugin->blacklist == NULL) 962 plugin->blacklist = GNUNET_CONTAINER_multihashmap_create(TRANSPORT_BLACKLIST_HT_SIZE);
958 {
959 plugin->blacklist = GNUNET_CONTAINER_multihashmap_create(100); /* FIXME: estimated number of peers or what? */
960 }
961
962 GNUNET_assert(plugin->blacklist != NULL); 963 GNUNET_assert(plugin->blacklist != NULL);
963 964 GNUNET_CONTAINER_multihashmap_put(plugin->blacklist, &peer->hashPubKey,
964 GNUNET_CONTAINER_multihashmap_put(plugin->blacklist, &peer->hashPubKey, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); 965 NULL,
966 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
965} 967}
966 968
969
967/** 970/**
968 * Read the blacklist file, containing transport:peer entries. 971 * Read the blacklist file, containing transport:peer entries.
969 * Provided the transport is loaded, set up hashmap with these 972 * Provided the transport is loaded, set up hashmap with these
@@ -1014,6 +1017,7 @@ read_blacklist_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1014 GNUNET_free (fn); 1017 GNUNET_free (fn);
1015 return; 1018 return;
1016 } 1019 }
1020 /* FIXME: use mmap */
1017 data = GNUNET_malloc_large (frstat.st_size); 1021 data = GNUNET_malloc_large (frstat.st_size);
1018 if (frstat.st_size != 1022 if (frstat.st_size !=
1019 GNUNET_DISK_fn_read (fn, data, frstat.st_size)) 1023 GNUNET_DISK_fn_read (fn, data, frstat.st_size))
@@ -1122,9 +1126,9 @@ read_blacklist_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1122 } 1126 }
1123 GNUNET_free (data); 1127 GNUNET_free (data);
1124 GNUNET_free (fn); 1128 GNUNET_free (fn);
1125
1126} 1129}
1127 1130
1131
1128/** 1132/**
1129 * Function called to notify a client about the socket being ready to 1133 * Function called to notify a client about the socket being ready to
1130 * queue more data. "buf" will be NULL and "size" zero if the socket 1134 * queue more data. "buf" will be NULL and "size" zero if the socket
@@ -2512,13 +2516,16 @@ add_hello_for_peer (void *cls,
2512 2516
2513/** 2517/**
2514 * Create a fresh entry in our neighbour list for the given peer. 2518 * Create a fresh entry in our neighbour list for the given peer.
2515 * Will try to transmit our current HELLO to the new neighbour. 2519 * Will try to transmit our current HELLO to the new neighbour.
2520 * Do not call this function directly, use 'setup_peer_check_blacklist.
2516 * 2521 *
2517 * @param peer the peer for which we create the entry 2522 * @param peer the peer for which we create the entry
2523 * @param do_hello should we schedule transmitting a HELLO
2518 * @return the new neighbour list entry 2524 * @return the new neighbour list entry
2519 */ 2525 */
2520static struct NeighbourList * 2526static struct NeighbourList *
2521setup_new_neighbour (const struct GNUNET_PeerIdentity *peer) 2527setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
2528 int do_hello)
2522{ 2529{
2523 struct NeighbourList *n; 2530 struct NeighbourList *n;
2524 struct TransportPlugin *tp; 2531 struct TransportPlugin *tp;
@@ -2558,18 +2565,65 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
2558 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched, 2565 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2559 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2566 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2560 &neighbour_timeout_task, n); 2567 &neighbour_timeout_task, n);
2561 n->piter = GNUNET_PEERINFO_iterate (cfg, sched, peer, 2568 if (do_hello)
2562 0, GNUNET_TIME_UNIT_FOREVER_REL, 2569 {
2563 &add_hello_for_peer, n); 2570 n->piter = GNUNET_PEERINFO_iterate (cfg, sched, peer,
2564 transmit_to_peer (NULL, NULL, 0, 2571 0, GNUNET_TIME_UNIT_FOREVER_REL,
2565 HELLO_ADDRESS_EXPIRATION, 2572 &add_hello_for_peer, n);
2566 (const char *) our_hello, GNUNET_HELLO_size(our_hello), 2573 transmit_to_peer (NULL, NULL, 0,
2567 GNUNET_NO, n); 2574 HELLO_ADDRESS_EXPIRATION,
2575 (const char *) our_hello, GNUNET_HELLO_size(our_hello),
2576 GNUNET_NO, n);
2577 }
2568 return n; 2578 return n;
2569} 2579}
2570 2580
2571 2581
2572/** 2582/**
2583 * Function called after we have checked if communicating
2584 * with a given peer is acceptable.
2585 *
2586 * @param cls closure
2587 * @param n NULL if communication is not acceptable
2588 */
2589typedef void (*SetupContinuation)(void *cls,
2590 struct NeighbourList *n);
2591
2592
2593
2594/**
2595 * Obtain a 'struct NeighbourList' for the given peer. If such an entry
2596 * does not yet exist, check the blacklist. If the blacklist says creating
2597 * one is acceptable, create one and call the continuation; otherwise
2598 * call the continuation with NULL.
2599 *
2600 * @param peer peer to setup or look up a struct NeighbourList for
2601 * @param do_hello should we also schedule sending our HELLO to the peer
2602 * if this is a new record
2603 * @param cont function to call with the 'struct NeigbhbourList*'
2604 * @param cont_cls closure for cont
2605 */
2606static void
2607setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
2608 int do_hello,
2609 SetupContinuation cont,
2610 void *cont_cls)
2611{
2612 struct NeighbourList *n;
2613
2614 n = find_neighbour(peer);
2615 if (n != NULL)
2616 {
2617 cont (cont_cls, n);
2618 return;
2619 }
2620 /* FIXME: do actual blacklist checking here... */
2621 cont (cont_cls,
2622 setup_new_neighbour (peer, do_hello));
2623}
2624
2625
2626/**
2573 * Send periodic PING messages to a give foreign address. 2627 * Send periodic PING messages to a give foreign address.
2574 * 2628 *
2575 * @param cls our 'struct PeriodicValidationContext*' 2629 * @param cls our 'struct PeriodicValidationContext*'
@@ -2997,6 +3051,79 @@ handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
2997 3051
2998 3052
2999/** 3053/**
3054 * Try to validate a neighbour's address by sending him our HELLO and a PING.
3055 *
3056 * @param cls the 'struct ValidationEntry*'
3057 * @param neighbour neighbour to validate, NULL if validation failed
3058 */
3059static void
3060transmit_hello_and_ping (void *cls,
3061 struct NeighbourList *neighbour)
3062{
3063 struct ValidationEntry *va = cls;
3064 struct ForeignAddressList *peer_address;
3065 struct TransportPingMessage ping;
3066 uint16_t hello_size;
3067 size_t tsize;
3068 char * message_buf;
3069
3070 if (neighbour == NULL)
3071 {
3072 /* FIXME: stats... */
3073 GNUNET_free (va->transport_name);
3074 GNUNET_free (va);
3075 return;
3076 }
3077 neighbour->publicKey = va->publicKey;
3078 neighbour->public_key_valid = GNUNET_YES;
3079 peer_address = add_peer_address (neighbour,
3080 va->transport_name, NULL,
3081 (const void*) &va[1],
3082 va->addrlen);
3083 if (peer_address == NULL)
3084 {
3085 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3086 "Failed to add peer `%4s' for plugin `%s'\n",
3087 GNUNET_i2s (&neighbour->id),
3088 va->transport_name);
3089 GNUNET_free (va->transport_name);
3090 GNUNET_free (va);
3091 return;
3092 }
3093 hello_size = GNUNET_HELLO_size(our_hello);
3094 tsize = sizeof(struct TransportPingMessage) + hello_size;
3095 message_buf = GNUNET_malloc(tsize);
3096 ping.challenge = htonl(va->challenge);
3097 ping.header.size = htons(sizeof(struct TransportPingMessage));
3098 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3099 memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3100 memcpy(message_buf, our_hello, hello_size);
3101 memcpy(&message_buf[hello_size],
3102 &ping,
3103 sizeof(struct TransportPingMessage));
3104#if DEBUG_TRANSPORT
3105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3106 "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
3107 GNUNET_a2s ((const void*) &va[1], va->addrlen),
3108 va->transport_name,
3109 GNUNET_i2s (&neighbour->id),
3110 "HELLO", hello_size,
3111 "PING", sizeof (struct TransportPingMessage));
3112#endif
3113 GNUNET_STATISTICS_update (stats,
3114 gettext_noop ("# PING messages sent for initial validation"),
3115 1,
3116 GNUNET_NO);
3117 transmit_to_peer (NULL, peer_address,
3118 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3119 HELLO_VERIFICATION_TIMEOUT,
3120 message_buf, tsize,
3121 GNUNET_YES, neighbour);
3122 GNUNET_free(message_buf);
3123}
3124
3125
3126/**
3000 * Check if the given address is already being validated; if not, 3127 * Check if the given address is already being validated; if not,
3001 * append the given address to the list of entries that are being be 3128 * append the given address to the list of entries that are being be
3002 * validated and initiate validation. 3129 * validated and initiate validation.
@@ -3018,14 +3145,8 @@ run_validation (void *cls,
3018 struct GNUNET_PeerIdentity id; 3145 struct GNUNET_PeerIdentity id;
3019 struct TransportPlugin *tp; 3146 struct TransportPlugin *tp;
3020 struct ValidationEntry *va; 3147 struct ValidationEntry *va;
3021 struct NeighbourList *neighbour;
3022 struct ForeignAddressList *peer_address;
3023 struct TransportPingMessage ping;
3024 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk; 3148 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
3025 struct CheckAddressExistsClosure caec; 3149 struct CheckAddressExistsClosure caec;
3026 char * message_buf;
3027 uint16_t hello_size;
3028 size_t tsize;
3029 3150
3030 GNUNET_assert (addr != NULL); 3151 GNUNET_assert (addr != NULL);
3031 GNUNET_STATISTICS_update (stats, 3152 GNUNET_STATISTICS_update (stats,
@@ -3106,49 +3227,9 @@ run_validation (void *cls,
3106 &id.hashPubKey, 3227 &id.hashPubKey,
3107 va, 3228 va,
3108 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 3229 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3109 neighbour = find_neighbour(&id); 3230 setup_peer_check_blacklist (&id, GNUNET_NO,
3110 if (neighbour == NULL) 3231 &transmit_hello_and_ping,
3111 neighbour = setup_new_neighbour(&id); 3232 va);
3112 neighbour->publicKey = va->publicKey;
3113 neighbour->public_key_valid = GNUNET_YES;
3114 peer_address = add_peer_address (neighbour, tname, NULL, addr, addrlen);
3115 if (peer_address == NULL)
3116 {
3117 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3118 "Attempted to add peer `%4s' for plugin `%s'\n",
3119 GNUNET_i2s (&id), tname);
3120 }
3121 GNUNET_assert(peer_address != NULL);
3122 hello_size = GNUNET_HELLO_size(our_hello);
3123 tsize = sizeof(struct TransportPingMessage) + hello_size;
3124 message_buf = GNUNET_malloc(tsize);
3125 ping.challenge = htonl(va->challenge);
3126 ping.header.size = htons(sizeof(struct TransportPingMessage));
3127 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3128 memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
3129 memcpy(message_buf, our_hello, hello_size);
3130 memcpy(&message_buf[hello_size],
3131 &ping,
3132 sizeof(struct TransportPingMessage));
3133#if DEBUG_TRANSPORT
3134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3135 "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
3136 GNUNET_a2s (addr, addrlen),
3137 tname,
3138 GNUNET_i2s (&id),
3139 "HELLO", hello_size,
3140 "PING", sizeof (struct TransportPingMessage));
3141#endif
3142 GNUNET_STATISTICS_update (stats,
3143 gettext_noop ("# PING messages sent for initial validation"),
3144 1,
3145 GNUNET_NO);
3146 transmit_to_peer (NULL, peer_address,
3147 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3148 HELLO_VERIFICATION_TIMEOUT,
3149 message_buf, tsize,
3150 GNUNET_YES, neighbour);
3151 GNUNET_free(message_buf);
3152 return GNUNET_OK; 3233 return GNUNET_OK;
3153} 3234}
3154 3235
@@ -3627,12 +3708,12 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
3627 struct NeighbourList *n; 3708 struct NeighbourList *n;
3628 struct GNUNET_TIME_Relative ret; 3709 struct GNUNET_TIME_Relative ret;
3629 3710
3630 if (is_blacklisted(peer, plugin)) 3711 if (is_blacklisted (peer, plugin))
3631 return GNUNET_TIME_UNIT_FOREVER_REL; 3712 return GNUNET_TIME_UNIT_FOREVER_REL;
3632 3713
3633 n = find_neighbour (peer); 3714 n = find_neighbour (peer);
3634 if (n == NULL) 3715 if (n == NULL)
3635 n = setup_new_neighbour (peer); 3716 n = setup_new_neighbour (peer, GNUNET_YES);
3636 service_context = n->plugins; 3717 service_context = n->plugins;
3637 while ((service_context != NULL) && (plugin != service_context->plugin)) 3718 while ((service_context != NULL) && (plugin != service_context->plugin))
3638 service_context = service_context->next; 3719 service_context = service_context->next;
@@ -3820,6 +3901,64 @@ handle_hello (void *cls,
3820 3901
3821 3902
3822/** 3903/**
3904 * Closure for 'transmit_client_message'; followed by
3905 * 'msize' bytes of the actual message.
3906 */
3907struct TransmitClientMessageContext
3908{
3909 /**
3910 * Client on whom's behalf we are sending.
3911 */
3912 struct GNUNET_SERVER_Client *client;
3913
3914 /**
3915 * Timeout for the transmission.
3916 */
3917 struct GNUNET_TIME_Absolute timeout;
3918
3919 /**
3920 * Message priority.
3921 */
3922 uint32_t priority;
3923
3924 /**
3925 * Size of the message in bytes.
3926 */
3927 uint16_t msize;
3928};
3929
3930
3931/**
3932 * Schedule transmission of a message we got from a client to a peer.
3933 *
3934 * @param cls the 'struct TransmitClientMessageContext*'
3935 * @param n destination, or NULL on error (in that case, drop the message)
3936 */
3937static void
3938transmit_client_message (void *cls,
3939 struct NeighbourList *n)
3940{
3941 struct TransmitClientMessageContext *tcmc = cls;
3942 struct TransportClient *tc;
3943
3944 tc = clients;
3945 while ((tc != NULL) && (tc->client != tcmc->client))
3946 tc = tc->next;
3947
3948 if (n != NULL)
3949 {
3950 transmit_to_peer (tc, NULL, tcmc->priority,
3951 GNUNET_TIME_absolute_get_remaining (tcmc->timeout),
3952 (char *)&tcmc[1],
3953 tcmc->msize, GNUNET_NO, n);
3954 }
3955 GNUNET_SERVER_receive_done (tcmc->client, GNUNET_OK);
3956 GNUNET_SERVER_client_drop (tcmc->client);
3957 GNUNET_free (tcmc);
3958}
3959
3960
3961/**
3823 * Handle SEND-message. 3962 * Handle SEND-message.
3824 * 3963 *
3825 * @param cls closure (always NULL) 3964 * @param cls closure (always NULL)
@@ -3831,10 +3970,9 @@ handle_send (void *cls,
3831 struct GNUNET_SERVER_Client *client, 3970 struct GNUNET_SERVER_Client *client,
3832 const struct GNUNET_MessageHeader *message) 3971 const struct GNUNET_MessageHeader *message)
3833{ 3972{
3834 struct TransportClient *tc;
3835 struct NeighbourList *n;
3836 const struct OutboundMessage *obm; 3973 const struct OutboundMessage *obm;
3837 const struct GNUNET_MessageHeader *obmm; 3974 const struct GNUNET_MessageHeader *obmm;
3975 struct TransmitClientMessageContext *tcmc;
3838 uint16_t size; 3976 uint16_t size;
3839 uint16_t msize; 3977 uint16_t msize;
3840 3978
@@ -3851,37 +3989,31 @@ handle_send (void *cls,
3851 size, 3989 size,
3852 GNUNET_NO); 3990 GNUNET_NO);
3853 obm = (const struct OutboundMessage *) message; 3991 obm = (const struct OutboundMessage *) message;
3992 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3993 msize = ntohs (obmm->size);
3854#if DEBUG_TRANSPORT 3994#if DEBUG_TRANSPORT
3855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3856 "Received `%s' request from client with target `%4s'\n", 3996 "Received `%s' request from client with target `%4s' and message of type %u and size %u\n",
3857 "SEND", GNUNET_i2s (&obm->peer)); 3997 "SEND", GNUNET_i2s (&obm->peer),
3998 ntohs (obmm->type),
3999 msize);
3858#endif 4000#endif
3859 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3860 msize = ntohs (obmm->size);
3861 if (size != msize + sizeof (struct OutboundMessage)) 4001 if (size != msize + sizeof (struct OutboundMessage))
3862 { 4002 {
3863 GNUNET_break (0); 4003 GNUNET_break (0);
3864 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4004 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3865 return; 4005 return;
3866 } 4006 }
3867 n = find_neighbour (&obm->peer); 4007 tcmc = GNUNET_malloc (sizeof (struct TransmitClientMessageContext) + msize);
3868 if (n == NULL) 4008 tcmc->client = client;
3869 n = setup_new_neighbour (&obm->peer); 4009 tcmc->priority = ntohl (obm->priority);
3870 tc = clients; 4010 tcmc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout));
3871 while ((tc != NULL) && (tc->client != client)) 4011 tcmc->msize = msize;
3872 tc = tc->next; 4012 memcpy (&tcmc[1], obmm, msize);
3873 4013 GNUNET_SERVER_client_keep (client);
3874#if DEBUG_TRANSPORT 4014 setup_peer_check_blacklist (&obm->peer, GNUNET_YES,
3875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4015 &transmit_client_message,
3876 "Client asked to transmit %u-byte message of type %u to `%4s'\n", 4016 tcmc);
3877 ntohs (obmm->size),
3878 ntohs (obmm->type), GNUNET_i2s (&obm->peer));
3879#endif
3880 transmit_to_peer (tc, NULL, ntohl (obm->priority),
3881 GNUNET_TIME_relative_ntoh (obm->timeout),
3882 (char *)obmm,
3883 ntohs (obmm->size), GNUNET_NO, n);
3884 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3885} 4017}
3886 4018
3887 4019