X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=inline;f=src%2Fnat%2Fgnunet-service-nat.c;h=f4755659f2cbd5f940e7df1d44dfc40e2dbce002;hb=8a5c5861114433d0d267885bb29f21a0c160d1f4;hp=8499a97243f7fd97c1e9d25aa22498df9188ebc7;hpb=1b4333f3a6a4f76aa76fc3abc21e8476ea0a92e3;p=oweals%2Fgnunet.git diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index 8499a9724..f4755659f 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c @@ -26,6 +26,13 @@ * The purpose of this service is to enable transports to * traverse NAT routers, by providing traversal options and * knowledge about the local network topology. + * + * TODO: + * - call GN_start_gnunet_nat_server_() if possible (i.e. + * when we find we have a non-global IPv4 address) + * - implement autoconfig + * - implmeent UPnPC/PMP-based NAT traversal + * - implement NEW logic for external IP detection */ #include "platform.h" #include @@ -35,6 +42,7 @@ #include "gnunet_statistics_service.h" #include "gnunet_nat_service.h" #include "gnunet-service-nat_stun.h" +#include "gnunet-service-nat_helper.h" #include "nat.h" #include @@ -135,6 +143,51 @@ struct LocalAddressList }; +/** + * External IP address as given to us via some STUN server. + */ +struct StunExternalIP +{ + /** + * Kept in a DLL. + */ + struct StunExternalIP *next; + + /** + * Kept in a DLL. + */ + struct StunExternalIP *prev; + + /** + * Task we run to remove this entry when it is stale. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * Our external IP address as reported by the + * STUN server. + */ + struct sockaddr_in external_addr; + + /** + * Address of the reporting STUN server. Used to + * detect when a STUN server changes its opinion + * to more quickly remove stale results. + */ + struct sockaddr_storage stun_server_addr; + + /** + * Number of bytes used in @e stun_server_addr. + */ + size_t stun_server_addr_len; +}; + + +/** + * Timeout to use when STUN data is considered stale. + */ +static struct GNUNET_TIME_Relative stun_stale_timeout; + /** * Handle to our current configuration. */ @@ -170,6 +223,16 @@ static struct LocalAddressList *lal_head; */ static struct LocalAddressList *lal_tail; +/** + * Kept in a DLL. + */ +static struct StunExternalIP *se_head; + +/** + * Kept in a DLL. + */ +static struct StunExternalIP *se_tail; + /** * Free the DLL starting at #lal_head. @@ -344,6 +407,43 @@ check_stun (void *cls, } +/** + * Notify all clients about our external IP address + * as reported by the STUN server. + * + * @param ip the external IP + * @param add #GNUNET_YES to add, #GNUNET_NO to remove + */ +static void +notify_clients_stun_change (const struct sockaddr_in *ip, + int add) +{ + /* FIXME: notify clients about add/drop */ +} + + +/** + * Function to be called when we decide that an + * external IP address as told to us by a STUN + * server has gone stale. + * + * @param cls the `struct StunExternalIP` to drop + */ +static void +stun_ip_timeout (void *cls) +{ + struct StunExternalIP *se = cls; + + se->timeout_task = NULL; + notify_clients_stun_change (&se->external_addr, + GNUNET_NO); + GNUNET_CONTAINER_DLL_remove (se_head, + se_tail, + se); + GNUNET_free (se); +} + + /** * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from * client. @@ -393,8 +493,7 @@ handle_stun (void *cls, payload_size, &external_addr)) { - /* FIXME: do something with "external_addr"! We - now know that a server at "sa" claims that + /* We now know that a server at "sa" claims that we are visible at IP "external_addr". We should (for some fixed period of time) tell @@ -408,7 +507,50 @@ handle_stun (void *cls, (with a sane default), so that the UDP plugin can tell how often to re-request STUN. */ - + struct StunExternalIP *se; + + /* Check if we had a prior response from this STUN server */ + for (se = se_head; NULL != se; se = se->next) + { + if ( (se->stun_server_addr_len != sa_len) || + (0 != memcmp (sa, + &se->stun_server_addr, + sa_len)) ) + continue; /* different STUN server */ + if (0 != memcmp (&external_addr, + &se->external_addr, + sizeof (struct sockaddr_in))) + { + /* external IP changed, update! */ + notify_clients_stun_change (&se->external_addr, + GNUNET_NO); + se->external_addr = external_addr; + notify_clients_stun_change (&se->external_addr, + GNUNET_YES); + } + /* update timeout */ + GNUNET_SCHEDULER_cancel (se->timeout_task); + se->timeout_task + = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout, + &stun_ip_timeout, + se); + return; + } + /* STUN server is completely new, create fresh entry */ + se = GNUNET_new (struct StunExternalIP); + se->external_addr = external_addr; + GNUNET_memcpy (&se->stun_server_addr, + sa, + sa_len); + se->stun_server_addr_len = sa_len; + se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout, + &stun_ip_timeout, + se); + GNUNET_CONTAINER_DLL_insert (se_head, + se_tail, + se); + notify_clients_stun_change (&se->external_addr, + GNUNET_NO); } GNUNET_SERVICE_client_continue (ch->client); } @@ -506,32 +648,13 @@ handle_request_connection_reversal (void *cls, GNUNET_SERVICE_client_drop (ch->client); return; } - /* FIXME: actually run the logic! */ + /* FIXME: actually run the logic by + calling 'GN_request_connection_reversal()' */ GNUNET_SERVICE_client_continue (ch->client); } -/** - * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_TEST message from - * client. - * - * @param cls client who sent the message - * @param message the message received - */ -static void -handle_test (void *cls, - const struct GNUNET_NAT_RequestTestMessage *message) -{ - struct ClientHandle *ch = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received REQUEST_TEST message from client\n"); - /* FIXME: actually process test request */ - GNUNET_SERVICE_client_continue (ch->client); -} - - /** * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message * from client. @@ -590,6 +713,16 @@ handle_autoconfig_request (void *cls, static void shutdown_task (void *cls) { + struct StunExternalIP *se; + + while (NULL != (se = se_head)) + { + GNUNET_CONTAINER_DLL_remove (se_head, + se_tail, + se); + GNUNET_SCHEDULER_cancel (se->timeout_task); + GNUNET_free (se); + } if (NULL != scan_task) { GNUNET_SCHEDULER_cancel (scan_task); @@ -990,6 +1123,12 @@ run (void *cls, struct GNUNET_SERVICE_Handle *service) { cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + "NAT", + "STUN_STALE", + &stun_stale_timeout)) + stun_stale_timeout = GNUNET_TIME_UNIT_HOURS; GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); stats = GNUNET_STATISTICS_create ("nat", @@ -1070,10 +1209,6 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, struct GNUNET_NAT_RequestConnectionReversalMessage, NULL), - GNUNET_MQ_hd_fixed_size (test, - GNUNET_MESSAGE_TYPE_NAT_REQUEST_TEST, - struct GNUNET_NAT_RequestTestMessage, - NULL), GNUNET_MQ_hd_var_size (autoconfig_request, GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG, struct GNUNET_NAT_AutoconfigRequestMessage,