From: Christian Grothoff Date: Thu, 4 Aug 2011 20:49:35 +0000 (+0000) Subject: implementing blacklist X-Git-Tag: initial-import-from-subversion-38251~17466 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ed4272a244d2770c42ffdb22c80cb4245fbcf538;p=oweals%2Fgnunet.git implementing blacklist --- diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 5c8a997a9..395823724 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -149,10 +149,10 @@ gnunet_service_transport_LDADD = \ gnunet_service_transport_new_SOURCES = \ gnunet-service-transport-new.c gnunet-service-transport.h \ - gnunet-service-transport_blacklist.h \ + gnunet-service-transport_blacklist.h gnunet-service-transport_blacklist.c \ gnunet-service-transport_clients.h gnunet-service-transport_clients.c \ gnunet-service-transport_hello.h gnunet-service-transport_hello.c \ - gnunet-service-transport_neighbours.h \ + gnunet-service-transport_neighbours.h gnunet-service-transport_neighbours.c \ gnunet-service-transport_plugins.h gnunet-service-transport_plugins.c \ gnunet-service-transport_validation.h gnunet_service_transport_new_LDADD = \ 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 @@ +/* + This file is part of GNUnet. + (C) 2010,2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file transport/gnunet-service-transport_blacklist.c + * @brief blacklisting implementation + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet-service-transport.h" +#include "gnunet-service-transport_blacklist.h" +#include "gnunet-service-transport_neighbours.h" +#include "transport.h" + + +/** + * Size of the blacklist hash map. + */ +#define TRANSPORT_BLACKLIST_HT_SIZE 64 + + +/** + * Context we use when performing a blacklist check. + */ +struct BlacklistCheck; + + +/** + * Information kept for each client registered to perform + * blacklisting. + */ +struct Blacklisters +{ + /** + * This is a linked list. + */ + struct Blacklisters *next; + + /** + * This is a linked list. + */ + struct Blacklisters *prev; + + /** + * Client responsible for this entry. + */ + struct GNUNET_SERVER_Client *client; + + /** + * Blacklist check that we're currently performing. + */ + struct BlacklistCheck *bc; + +}; + + + +/** + * Context we use when performing a blacklist check. + */ +struct BlacklistCheck +{ + + /** + * This is a linked list. + */ + struct BlacklistCheck *next; + + /** + * This is a linked list. + */ + struct BlacklistCheck *prev; + + /** + * Peer being checked. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Continuation to call with the result. + */ + GST_BlacklistTestContinuation cont; + + /** + * Closure for cont. + */ + void *cont_cls; + + /** + * Current transmission request handle for this client, or NULL if no + * request is pending. + */ + struct GNUNET_CONNECTION_TransmitHandle *th; + + /** + * Our current position in the blacklisters list. + */ + struct Blacklisters *bl_pos; + + /** + * Current task performing the check. + */ + GNUNET_SCHEDULER_TaskIdentifier task; + +}; + + +/** + * Head of DLL of active blacklisting queries. + */ +static struct BlacklistCheck *bc_head; + +/** + * Tail of DLL of active blacklisting queries. + */ +static struct BlacklistCheck *bc_tail; + +/** + * Head of DLL of blacklisting clients. + */ +static struct Blacklisters *bl_head; + +/** + * Tail of DLL of blacklisting clients. + */ +static struct Blacklisters *bl_tail; + +/** + * Hashmap of blacklisted peers. Values are of type 'char *' (transport names), + * can be NULL if we have no static blacklist. + */ +static struct GNUNET_CONTAINER_MultiHashMap *blacklist; + + +/** + * Perform next action in the blacklist check. + * + * @param cls the 'struct BlacklistCheck*' + * @param tc unused + */ +static void +do_blacklist_check (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure (unused) + * @param client identification of the client + */ +static void +client_disconnect_notification (void *cls, + struct GNUNET_SERVER_Client *client) +{ + struct Blacklisters *bl; + struct BlacklistCheck *bc; + + if (client == NULL) + return; + for (bl = bl_head; bl != NULL; bl = bl->next) + { + if (bl->client != client) + continue; + for (bc = bc_head; bc != NULL; bc = bc->next) + { + if (bc->bl_pos != bl) + continue; + bc->bl_pos = bl->next; + if (bc->th != NULL) + { + GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th); + bc->th = NULL; + } + if (bc->task == GNUNET_SCHEDULER_NO_TASK) + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); + break; + } + GNUNET_CONTAINER_DLL_remove (bl_head, + bl_tail, + bl); + GNUNET_SERVER_client_drop (bl->client); + GNUNET_free (bl); + break; + } +} + + +/** + * Read the blacklist file, containing transport:peer entries. + * Provided the transport is loaded, set up hashmap with these + * entries to blacklist peers by transport. + * + */ +static void +read_blacklist_file () +{ + char *fn; + char *data; + size_t pos; + size_t colon_pos; + int tsize; + struct GNUNET_PeerIdentity pid; + struct stat frstat; + struct GNUNET_CRYPTO_HashAsciiEncoded enc; + unsigned int entries_found; + char *transport_name; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (GST_cfg, + "TRANSPORT", + "BLACKLIST_FILE", + &fn)) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Option `%s' in section `%s' not specified!\n", + "BLACKLIST_FILE", + "TRANSPORT"); +#endif + return; + } + if (GNUNET_OK != GNUNET_DISK_file_test (fn)) + GNUNET_DISK_fn_write (fn, NULL, 0, + GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); + if (0 != STAT (fn, &frstat)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not read blacklist file `%s'\n"), + fn); + GNUNET_free (fn); + return; + } + if (frstat.st_size == 0) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Blacklist file `%s' is empty.\n"), + fn); +#endif + GNUNET_free (fn); + return; + } + /* FIXME: use mmap */ + data = GNUNET_malloc_large (frstat.st_size); + GNUNET_assert(data != NULL); + if (frstat.st_size != + GNUNET_DISK_fn_read (fn, data, frstat.st_size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to read blacklist from `%s'\n"), + fn); + GNUNET_free (fn); + GNUNET_free (data); + return; + } + entries_found = 0; + pos = 0; + while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos])) + pos++; + while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) && + (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))) + { + colon_pos = pos; + while ( (colon_pos < frstat.st_size) && + (data[colon_pos] != ':') && + (! isspace ( (unsigned char) data[colon_pos])) ) + colon_pos++; + if (colon_pos >= frstat.st_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error in blacklist file at offset %llu, giving up!\n"), + (unsigned long long) colon_pos); + GNUNET_free (fn); + GNUNET_free (data); + return; + } + + if (isspace( (unsigned char) data[colon_pos])) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"), + (unsigned long long) colon_pos); + pos = colon_pos; + while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos])) + pos++; + continue; + } + tsize = colon_pos - pos; + if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) || (tsize == 0)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error in blacklist file at offset %llu, giving up!\n"), + (unsigned long long) colon_pos); + GNUNET_free (fn); + GNUNET_free (data); + return; + } + + if (tsize < 1) + continue; + + transport_name = GNUNET_malloc(tsize + 1); + memcpy(transport_name, &data[pos], tsize); + pos = colon_pos + 1; +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Read transport name `%s' in blacklist file.\n", + transport_name); +#endif + memcpy (&enc, + &data[pos], + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); + if (! isspace ( (unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1])) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"), + (unsigned long long) pos); + pos++; + while ((pos < frstat.st_size) && (!isspace ( (unsigned char) data[pos]))) + pos++; + GNUNET_free_non_null(transport_name); + continue; + } + enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; + if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error in blacklist file at offset %llu, skipping bytes `%s'.\n"), + (unsigned long long) pos, + &enc); + } + else + { + if (0 != memcmp (&pid, + &GST_my_identity, + sizeof (struct GNUNET_PeerIdentity))) + { + entries_found++; + GST_blacklist_add_peer (&pid, + transport_name); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Found myself `%s' in blacklist (useless, ignored)\n"), + GNUNET_i2s (&pid)); + } + } + pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded); + GNUNET_free_non_null(transport_name); + while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos])) + pos++; + } + GNUNET_STATISTICS_update (GST_stats, + "# Transport entries blacklisted", + entries_found, + GNUNET_NO); + GNUNET_free (data); + GNUNET_free (fn); +} + + +/** + * Start blacklist subsystem. + * + * @param server server used to accept clients from + */ +void +GST_blacklist_start (struct GNUNET_SERVER_Handle *server) +{ + read_blacklist_file (); + GNUNET_SERVER_disconnect_notify (server, + &client_disconnect_notification, + NULL); +} + + +/** + * Free the given entry in the blacklist. + * + * @param cls unused + * @param key host identity (unused) + * @param value the blacklist entry + * @return GNUNET_OK (continue to iterate) + */ +static int +free_blacklist_entry (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + char *be = value; + + GNUNET_free (be); + return GNUNET_OK; +} + + +/** + * Stop blacklist subsystem. + */ +void +GST_blacklist_stop () +{ + if (NULL != blacklist) + { + GNUNET_CONTAINER_multihashmap_iterate (blacklist, + &free_blacklist_entry, + NULL); + GNUNET_CONTAINER_multihashmap_destroy (blacklist); + blacklist = NULL; + } +} + + +/** + * Transmit blacklist query to the client. + * + * @param cls the 'struct BlacklistCheck' + * @param size number of bytes allowed + * @param buf where to copy the message + * @return number of bytes copied to buf + */ +static size_t +transmit_blacklist_message (void *cls, + size_t size, + void *buf) +{ + struct BlacklistCheck *bc = cls; + struct Blacklisters *bl; + struct BlacklistMessage bm; + + bc->th = NULL; + if (size == 0) + { + GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK); + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to send blacklist test for peer `%s' to client\n", + GNUNET_i2s (&bc->peer)); + return 0; + } +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending blacklist test for peer `%s' to client\n", + GNUNET_i2s (&bc->peer)); +#endif + bl = bc->bl_pos; + bm.header.size = htons (sizeof (struct BlacklistMessage)); + bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); + bm.is_allowed = htonl (0); + bm.peer = bc->peer; + memcpy (buf, &bm, sizeof (bm)); + GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); + return sizeof (bm); +} + + +/** + * Perform next action in the blacklist check. + * + * @param cls the 'struct BlacklistCheck*' + * @param tc unused + */ +static void +do_blacklist_check (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct BlacklistCheck *bc = cls; + struct Blacklisters *bl; + + bc->task = GNUNET_SCHEDULER_NO_TASK; + bl = bc->bl_pos; + if (bl == NULL) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No other blacklist clients active, will allow neighbour `%s'\n", + GNUNET_i2s (&bc->peer)); +#endif + bc->cont (bc->cont_cls, + &bc->peer, + GNUNET_OK); + GNUNET_free (bc); + return; + } + if (bl->bc != NULL) + return; /* someone else busy with this client */ + bl->bc = bc; + bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client, + sizeof (struct BlacklistMessage), + GNUNET_TIME_UNIT_FOREVER_REL, + &transmit_blacklist_message, + bc); +} + + +/** + * Got the result about an existing connection from a new blacklister. + * Shutdown the neighbour if necessary. + * + * @param cls unused + * @param peer the neighbour that was investigated + * @param allowed GNUNET_OK if we can keep it, + * GNUNET_NO if we must shutdown the connection + */ +static void +confirm_or_drop_neighbour (void *cls, + const struct GNUNET_PeerIdentity *peer, + int allowed) +{ + if (GNUNET_OK == allowed) + return; /* we're done */ + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# disconnects due to blacklist"), + 1, + GNUNET_NO); + GST_neighbours_force_disconnect (peer); +} + + +/** + * Closure for 'test_connection_ok'. + */ +struct TestConnectionContext +{ + /** + * Is this the first neighbour we're checking? + */ + int first; + + /** + * Handle to the blacklisting client we need to ask. + */ + struct Blacklisters *bl; +}; + + +/** + * Test if an existing connection is still acceptable given a new + * blacklisting client. + * + * @param cls the 'struct TestConnectionContest' + * @param pid neighbour's identity + */ +static void +test_connection_ok (void *cls, + const struct GNUNET_PeerIdentity *neighbour) +{ + struct TestConnectionContext *tcc = cls; + struct BlacklistCheck *bc; + + bc = GNUNET_malloc (sizeof (struct BlacklistCheck)); + GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); + bc->peer = *neighbour; + bc->cont = &confirm_or_drop_neighbour; + bc->cont_cls = NULL; + bc->bl_pos = tcc->bl; + if (GNUNET_YES == tcc->first) + { + /* all would wait for the same client, no need to + create more than just the first task right now */ + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); + tcc->first = GNUNET_NO; + } +} + + + +/** + * Initialize a blacklisting client. We got a blacklist-init + * message from this client, add him to the list of clients + * to query for blacklisting. + * + * @param cls unused + * @param client the client + * @param message the blacklist-init message that was sent + */ +void +GST_blacklist_handle_init (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + struct Blacklisters *bl; + struct TestConnectionContext tcc; + + bl = bl_head; + while (bl != NULL) + { + if (bl->client == client) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + bl = bl->next; + } + bl = GNUNET_malloc (sizeof (struct Blacklisters)); + bl->client = client; + GNUNET_SERVER_client_keep (client); + GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl); + + /* confirm that all existing connections are OK! */ + tcc.bl = bl; + tcc.first = GNUNET_YES; + GST_neighbours_iterate (&test_connection_ok, + &tcc); +} + + +/** + * A blacklisting client has sent us reply. Process it. + * + * @param cls unused + * @param client the client + * @param message the blacklist-init message that was sent + */ +void +GST_blacklist_handle_reply (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message; + struct Blacklisters *bl; + struct BlacklistCheck *bc; + + bl = bl_head; + while ( (bl != NULL) && + (bl->client != client) ) + bl = bl->next; + if (bl == NULL) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Blacklist client disconnected\n"); +#endif + /* FIXME: other error handling here!? */ + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + bc = bl->bc; + bl->bc = NULL; + if (ntohl (msg->is_allowed) == GNUNET_SYSERR) + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Blacklist check failed, peer not allowed\n"); +#endif + bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO); + GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); + GNUNET_free (bc); + } + else + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Blacklist check succeeded, continuing with checks\n"); +#endif + bc->bl_pos = bc->bl_pos->next; + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); + } + /* check if any other bc's are waiting for this blacklister */ + bc = bc_head; + while (bc != NULL) + { + if ( (bc->bl_pos == bl) && + (GNUNET_SCHEDULER_NO_TASK == bc->task) ) + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); + bc = bc->next; + } +} + + +/** + * Add the given peer to the blacklist (for the given transport). + * + * @param peer peer to blacklist + * @param transport_name transport to blacklist for this peer, NULL for all + */ +void +GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, + const char *transport_name) +{ +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding peer `%s' with plugin `%s' to blacklist\n", + GNUNET_i2s (peer), + transport_name); +#endif + if (blacklist == NULL) + blacklist = GNUNET_CONTAINER_multihashmap_create(TRANSPORT_BLACKLIST_HT_SIZE); + GNUNET_CONTAINER_multihashmap_put (blacklist, + &peer->hashPubKey, + GNUNET_strdup (transport_name), + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); +} + + +/** + * Test if the given blacklist entry matches. If so, + * abort the iteration. + * + * @param cls the transport name to match (const char*) + * @param key the key (unused) + * @param value the 'char *' (name of a blacklisted transport) + * @return GNUNET_OK if the entry does not match, GNUNET_NO if it matches + */ +static int +test_blacklisted (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + const char *transport_name = cls; + char *be = value; + + if (0 == strcmp (transport_name, + be)) + return GNUNET_NO; /* abort iteration! */ + return GNUNET_OK; +} + + +/** + * Test if a peer/transport combination is blacklisted. + * + * @param peer the identity of the peer to test + * @param transport_name name of the transport to test, never NULL + * @param cont function to call with result + * @param cont_cls closure for 'cont' + */ +void +GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, + const char *transport_name, + GST_BlacklistTestContinuation cont, + void *cont_cls) +{ + struct BlacklistCheck *bc; + + if ( (blacklist != NULL) && + (GNUNET_SYSERR == + GNUNET_CONTAINER_multihashmap_get_multiple (blacklist, + &peer->hashPubKey, + &test_blacklisted, + (void*) transport_name)) ) + { + /* disallowed by config, disapprove instantly */ + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# disconnects due to blacklist"), + 1, + GNUNET_NO); + if (cont != NULL) + cont (cont_cls, peer, GNUNET_NO); + return; + } + + if (bl_head == NULL) + { + /* no blacklist clients, approve instantly */ + if (cont != NULL) + cont (cont_cls, peer, GNUNET_OK); + return; + } + + /* need to query blacklist clients */ + bc = GNUNET_malloc (sizeof (struct BlacklistCheck)); + GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); + bc->peer = *peer; + bc->cont = cont; + bc->cont_cls = cont_cls; + bc->bl_pos = bl_head; + bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, + bc); +} + + + +/* end of file gnunet-service-transport_blacklist.c */ diff --git a/src/transport/gnunet-service-transport_blacklist.h b/src/transport/gnunet-service-transport_blacklist.h index 1d10846ea..03f059d81 100644 --- a/src/transport/gnunet-service-transport_blacklist.h +++ b/src/transport/gnunet-service-transport_blacklist.h @@ -30,37 +30,52 @@ #include "gnunet_util_lib.h" /** + * Start blacklist subsystem. * + * @param server server used to accept clients from */ void -GST_blacklist_start (void); +GST_blacklist_start (struct GNUNET_SERVER_Handle *server); /** - * + * Stop blacklist subsystem. */ void GST_blacklist_stop (void); /** + * Initialize a blacklisting client. We got a blacklist-init + * message from this client, add him to the list of clients + * to query for blacklisting. * + * @param cls unused + * @param client the client + * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_init (void *cls, - const struct GNUNET_SERVER_Client *client, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** + * A blacklisting client has sent us reply. Process it. * + * @param cls unused + * @param client the client + * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_reply (void *cls, - const struct GNUNET_SERVER_Client *client, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** - * + * Add the given peer to the blacklist (for the given transport). + * + * @param peer peer to blacklist + * @param transport_name transport to blacklist for this peer, NULL for all */ void GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, @@ -68,11 +83,31 @@ GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, /** + * Continuation called from a blacklist test. + * + * @param cls closure + * @param peer identity of peer that was tested + * @param result GNUNET_OK if the connection is allowed, + * GNUNET_NO if not + */ +typedef void (*GST_BlacklistTestContinuation)(void *cls, + const struct GNUNET_PeerIdentity *peer, + int result); + + +/** + * Test if a peer/transport combination is blacklisted. * + * @param peer the identity of the peer to test + * @param transport_name name of the transport to test, never NULL + * @param cont function to call with result + * @param cont_cls closure for 'cont' */ -int -GST_blacklist_test (const struct GNUNET_PeerIdentity *peer, - const char *transport_name); +void +GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, + const char *transport_name, + GST_BlacklistTestContinuation cont, + void *cont_cls); diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c new file mode 100644 index 000000000..4107c0012 --- /dev/null +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -0,0 +1,176 @@ +/* + This file is part of GNUnet. + (C) 2010,2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file transport/gnunet-service-transport_neighbours.c + * @brief neighbour management + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet-service-transport_neighbours.h" +#include "gnunet-service-transport.h" + +// TODO: +// - have a way to access the currently 'connected' session +// (for sending and to notice disconnect of it!) +// - have a way to access/update bandwidth/quota information per peer +// (for CostReport/TrafficReport callbacks) + + + +/** + * Initialize the neighbours subsystem. + * + * @param cls closure for callbacks + * @param connect_cb function to call if we connect to a peer + * @param disconnect_cb function to call if we disconnect from a peer + */ +void +GST_neighbours_start (void *cls, + GNUNET_TRANSPORT_NotifyConnect connect_cb, + GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb) +{ +} + + +/** + * Cleanup the neighbours subsystem. + */ +void +GST_neighbours_stop () +{ +} + + +/** + * Try to create a connection to the given target (eventually). + * + * @param target peer to try to connect to + */ +void +GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target) +{ +} + + +/** + * Test if we're connected to the given peer. + * + * @param target peer to test + * @return GNUNET_YES if we are connected, GNUNET_NO if not + */ +int +GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target) +{ + return GNUNET_NO; +} + + +/** + * If we have an active connection to the given target, it must be shutdown. + * + * @param target peer to disconnect from + */ +void +GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target) +{ +} + + +/** + * Iterate over all connected neighbours. + * + * @param cb function to call + * @param cb_cls closure for cb + */ +void +GST_neighbours_iterate (GST_NeighbourIterator cb, + void *cb_cls) +{ +} + + +/** + * We have received a PONG. Update lifeness of the neighbour. + * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not + */ +int +GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *hdr, + const char *plugin_name, + const void *sender_address, + size_t sender_address_len) +{ + return GNUNET_SYSERR; +} + + +/** + * We have received a CONNECT. Set the peer to connected. + * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not + */ +int +GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *hdr, + const char *plugin_name, + const void *sender_address, + size_t sender_address_len) +{ + return GNUNET_SYSERR; +} + + +/** + * We have received a DISCONNECT. Set the peer to disconnected. + * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not + */ +int +GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *hdr, + const char *plugin_name, + const void *sender_address, + size_t sender_address_len) +{ + return GNUNET_SYSERR; +} + + +/* end of file gnunet-service-transport_neighbours.c */ diff --git a/src/transport/gnunet-service-transport_neighbours.h b/src/transport/gnunet-service-transport_neighbours.h index c627e7e2f..914134ac5 100644 --- a/src/transport/gnunet-service-transport_neighbours.h +++ b/src/transport/gnunet-service-transport_neighbours.h @@ -20,7 +20,7 @@ /** * @file transport/gnunet-service-transport_neighbours.h - * @brief plugin management API + * @brief neighbour management API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_NEIGHBOURS_H @@ -30,51 +30,93 @@ #include "gnunet_transport_service.h" #include "gnunet_util_lib.h" +// TODO: +// - have a way to access the currently 'connected' session +// (for sending and to notice disconnect of it!) +// - have a way to access/update bandwidth/quota information per peer +// (for CostReport/TrafficReport callbacks) + + /** + * Initialize the neighbours subsystem. * + * @param cls closure for callbacks + * @param connect_cb function to call if we connect to a peer + * @param disconnect_cb function to call if we disconnect from a peer */ void GST_neighbours_start (void *cls, GNUNET_TRANSPORT_NotifyConnect connect_cb, GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb); + /** - * + * Cleanup the neighbours subsystem. */ void GST_neighbours_stop (void); + /** + * Try to create a connection to the given target (eventually). * + * @param target peer to try to connect to */ void GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target); + /** - * + * Test if we're connected to the given peer. + * + * @param target peer to test + * @return GNUNET_YES if we are connected, GNUNET_NO if not */ int GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target); + /** + * If we have an active connection to the given target, it must be shutdown. * + * @param target peer to disconnect from */ void GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target); +/** + * Function called for each connected neighbour. + * + * @param cls closure + * @param neighbour identity of the neighbour + */ typedef void (*GST_NeighbourIterator)(void *cls, const struct GNUNET_PeerIdentity *neighbour); +/** + * Iterate over all connected neighbours. + * + * @param cb function to call + * @param cb_cls closure for cb + */ void GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls); /** + * We have received a PONG. Update lifeness of the neighbour. * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not */ int GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender, @@ -83,8 +125,17 @@ GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender, const void *sender_address, size_t sender_address_len); + /** + * We have received a CONNECT. Set the peer to connected. * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not */ int GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender, @@ -93,8 +144,17 @@ GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender, const void *sender_address, size_t sender_address_len); + /** + * We have received a DISCONNECT. Set the peer to disconnected. * + * @param sender peer sending the PONG + * @param hdr the PONG message (presumably) + * @param plugin_name name of transport that delivered the PONG + * @param sender_address address of the other peer, NULL if other peer + * connected to us + * @param sender_address_len number of bytes in sender_address + * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not */ int GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender, @@ -104,7 +164,5 @@ GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender, size_t sender_address_len); - - #endif /* end of file gnunet-service-transport_neighbours.h */