From 80e1315b56f559db60499f5373e90c293c5ab065 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 6 Jan 2017 13:26:38 +0100 Subject: separate service for autoconfiguration from NAT traversal --- src/nat/gnunet-service-nat.c | 355 ------------------------------------------- 1 file changed, 355 deletions(-) (limited to 'src/nat/gnunet-service-nat.c') diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index 79f806f27..2cb2b30ff 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c @@ -283,80 +283,6 @@ struct StunExternalIP }; -/** - * Context for autoconfiguration operations. - */ -struct AutoconfigContext -{ - /** - * Kept in a DLL. - */ - struct AutoconfigContext *prev; - - /** - * Kept in a DLL. - */ - struct AutoconfigContext *next; - - /** - * Which client asked the question. - */ - struct ClientHandle *ch; - - /** - * Configuration we are creating. - */ - struct GNUNET_CONFIGURATION_Handle *c; - - /** - * Original configuration (for diffing). - */ - struct GNUNET_CONFIGURATION_Handle *orig; - - /** - * Timeout task to force termination. - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * What type of system are we on? - */ - char *system_type; - - /** - * Handle to activity to probe for our external IP. - */ - struct GNUNET_NAT_ExternalHandle *probe_external; - - /** - * #GNUNET_YES if upnpc should be used, - * #GNUNET_NO if upnpc should not be used, - * #GNUNET_SYSERR if we should simply not change the option. - */ - int enable_upnpc; - - /** - * Status code to return to the client. - */ - enum GNUNET_NAT_StatusCode status_code; - - /** - * NAT type to return to the client. - */ - enum GNUNET_NAT_Type type; -}; - - -/** - * DLL of our autoconfiguration operations. - */ -static struct AutoconfigContext *ac_head; - -/** - * DLL of our autoconfiguration operations. - */ -static struct AutoconfigContext *ac_tail; - /** * Timeout to use when STUN data is considered stale. */ @@ -1919,274 +1845,6 @@ handle_request_connection_reversal (void *cls, } -/** - * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message - * from client. - * - * @param cls client who sent the message - * @param message the message received - * @return #GNUNET_OK if message is well-formed - */ -static int -check_autoconfig_request (void *cls, - const struct GNUNET_NAT_AutoconfigRequestMessage *message) -{ - return GNUNET_OK; /* checked later */ -} - - -/** - * Stop all pending activities with respect to the @a ac - * - * @param ac autoconfiguration to terminate activities for - */ -static void -terminate_ac_activities (struct AutoconfigContext *ac) -{ - if (NULL != ac->probe_external) - { - GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external); - ac->probe_external = NULL; - } - if (NULL != ac->timeout_task) - { - GNUNET_SCHEDULER_cancel (ac->timeout_task); - ac->timeout_task = NULL; - } -} - - -/** - * Finish handling the autoconfiguration request and send - * the response to the client. - * - * @param cls the `struct AutoconfigContext` to conclude - */ -static void -conclude_autoconfig_request (void *cls) -{ - struct AutoconfigContext *ac = cls; - struct ClientHandle *ch = ac->ch; - struct GNUNET_NAT_AutoconfigResultMessage *arm; - struct GNUNET_MQ_Envelope *env; - size_t c_size; - char *buf; - struct GNUNET_CONFIGURATION_Handle *diff; - - ac->timeout_task = NULL; - terminate_ac_activities (ac); - - /* Send back response */ - diff = GNUNET_CONFIGURATION_get_diff (ac->orig, - ac->c); - buf = GNUNET_CONFIGURATION_serialize (diff, - &c_size); - GNUNET_CONFIGURATION_destroy (diff); - env = GNUNET_MQ_msg_extra (arm, - c_size, - GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT); - arm->status_code = htonl ((uint32_t) ac->status_code); - arm->type = htonl ((uint32_t) ac->type); - GNUNET_memcpy (&arm[1], - buf, - c_size); - GNUNET_free (buf); - GNUNET_MQ_send (ch->mq, - env); - - /* clean up */ - GNUNET_free (ac->system_type); - GNUNET_CONFIGURATION_destroy (ac->orig); - GNUNET_CONFIGURATION_destroy (ac->c); - GNUNET_CONTAINER_DLL_remove (ac_head, - ac_tail, - ac); - GNUNET_free (ac); - GNUNET_SERVICE_client_continue (ch->client); -} - - -/** - * Check if all autoconfiguration operations have concluded, - * and if they have, send the result back to the client. - * - * @param ac autoconfiguation context to check - */ -static void -check_autoconfig_finished (struct AutoconfigContext *ac) -{ - if (NULL != ac->probe_external) - return; - GNUNET_SCHEDULER_cancel (ac->timeout_task); - ac->timeout_task - = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request, - ac); -} - - -/** - * Update ENABLE_UPNPC configuration option. - * - * @param ac autoconfiguration to update - */ -static void -update_enable_upnpc_option (struct AutoconfigContext *ac) -{ - switch (ac->enable_upnpc) - { - case GNUNET_YES: - GNUNET_CONFIGURATION_set_value_string (ac->c, - "NAT", - "ENABLE_UPNP", - "YES"); - break; - case GNUNET_NO: - GNUNET_CONFIGURATION_set_value_string (ac->c, - "NAT", - "ENABLE_UPNP", - "NO"); - break; - case GNUNET_SYSERR: - /* We are unsure, do not change option */ - break; - } -} - - -/** - * Handle result from external IP address probe during - * autoconfiguration. - * - * @param cls our `struct AutoconfigContext` - * @param addr the address, NULL on errors - * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code - */ -static void -auto_external_result_cb (void *cls, - const struct in_addr *addr, - enum GNUNET_NAT_StatusCode result) -{ - struct AutoconfigContext *ac = cls; - - ac->probe_external = NULL; - switch (result) - { - case GNUNET_NAT_ERROR_SUCCESS: - ac->enable_upnpc = GNUNET_YES; - break; - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: - case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: - case GNUNET_NAT_ERROR_IPC_FAILURE: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Disabling UPNPC: %d\n", - (int) result); - ac->enable_upnpc = GNUNET_NO; /* did not work */ - break; - default: - GNUNET_break (0); /* unexpected */ - ac->enable_upnpc = GNUNET_SYSERR; - break; - } - update_enable_upnpc_option (ac); - check_autoconfig_finished (ac); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from - * client. - * - * @param cls client who sent the message - * @param message the message received - */ -static void -handle_autoconfig_request (void *cls, - const struct GNUNET_NAT_AutoconfigRequestMessage *message) -{ - struct ClientHandle *ch = cls; - size_t left = ntohs (message->header.size) - sizeof (*message); - struct LocalAddressList *lal; - struct AutoconfigContext *ac; - - ac = GNUNET_new (struct AutoconfigContext); - ac->status_code = GNUNET_NAT_ERROR_SUCCESS; - ac->ch = ch; - ac->c = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_deserialize (ac->c, - (const char *) &message[1], - left, - GNUNET_NO)) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (ch->client); - GNUNET_CONFIGURATION_destroy (ac->c); - GNUNET_free (ac); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received REQUEST_AUTO_CONFIG message from client\n"); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (ac->c, - "PEER", - "SYSTEM_TYPE", - &ac->system_type)) - ac->system_type = GNUNET_strdup ("UNKNOWN"); - - GNUNET_CONTAINER_DLL_insert (ac_head, - ac_tail, - ac); - ac->orig - = GNUNET_CONFIGURATION_dup (ac->c); - ac->timeout_task - = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT, - &conclude_autoconfig_request, - ac); - ac->enable_upnpc = GNUNET_SYSERR; /* undecided */ - - /* Probe for upnpc */ - if (GNUNET_SYSERR == - GNUNET_OS_check_helper_binary ("upnpc", - GNUNET_NO, - NULL)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("UPnP client `upnpc` command not found, disabling UPnP\n")); - ac->enable_upnpc = GNUNET_NO; - } - else - { - for (lal = lal_head; NULL != lal; lal = lal->next) - if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN)) - /* we are behind NAT, useful to try upnpc */ - ac->enable_upnpc = GNUNET_YES; - } - if (GNUNET_YES == ac->enable_upnpc) - { - /* If we are a mobile device, always leave it on as the network - may change to one that supports UPnP anytime. If we are - stationary, check if our network actually supports UPnP, and if - not, disable it. */ - if ( (0 == strcasecmp (ac->system_type, - "INFRASTRUCTURE")) || - (0 == strcasecmp (ac->system_type, - "DESKTOP")) ) - { - /* Check if upnpc gives us an external IP */ - ac->probe_external - = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb, - ac); - } - } - if (NULL == ac->probe_external) - update_enable_upnpc_option (ac); - - /* Finally, check if we are already done */ - check_autoconfig_finished (ac); -} - - /** * Task run during shutdown. * @@ -2196,16 +1854,7 @@ static void shutdown_task (void *cls) { struct StunExternalIP *se; - struct AutoconfigContext *ac; - while (NULL != (ac = ac_head)) - { - GNUNET_CONTAINER_DLL_remove (ac_head, - ac_tail, - ac); - terminate_ac_activities (ac); - GNUNET_free (ac); - } while (NULL != (se = se_head)) { GNUNET_CONTAINER_DLL_remove (se_head, @@ -2386,10 +2035,6 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, struct GNUNET_NAT_RequestConnectionReversalMessage, NULL), - GNUNET_MQ_hd_var_size (autoconfig_request, - GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG, - struct GNUNET_NAT_AutoconfigRequestMessage, - NULL), GNUNET_MQ_handler_end ()); -- cgit v1.2.3