X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fnat%2Fnat_api.c;h=69612584e879922f6be69fd0417ca5a4afe37be6;hb=a3e88087d09186d847ee8bf042ad665ab6cb0850;hp=3fe97ed85108b198dc32c719054adf72af6c0f0b;hpb=545faeda8f7fb7e03bb39602df6142f630157050;p=oweals%2Fgnunet.git diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c index 3fe97ed85..69612584e 100644 --- a/src/nat/nat_api.c +++ b/src/nat/nat_api.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2007-2016 GNUnet e.V. + Copyright (C) 2007-2017 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -48,6 +48,11 @@ struct AddrEntry */ struct AddrEntry *prev; + /** + * Address class of the address. + */ + enum GNUNET_NAT_AddressClass ac; + /** * Number of bytes that follow. */ @@ -65,7 +70,7 @@ struct GNUNET_NAT_Handle * Configuration we use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; - + /** * Message queue for communicating with the NAT service. */ @@ -75,7 +80,7 @@ struct GNUNET_NAT_Handle * Our registration message. */ struct GNUNET_MessageHeader *reg; - + /** * Head of address DLL. */ @@ -90,12 +95,12 @@ struct GNUNET_NAT_Handle * Function to call when our addresses change. */ GNUNET_NAT_AddressCallback address_callback; - + /** * Function to call when another peer requests connection reversal. */ GNUNET_NAT_ReversalCallback reversal_callback; - + /** * Closure for the various callbacks. */ @@ -130,11 +135,25 @@ do_connect (void *cls); static void reconnect (struct GNUNET_NAT_Handle *nh) { + struct AddrEntry *ae; + if (NULL != nh->mq) { GNUNET_MQ_destroy (nh->mq); nh->mq = NULL; } + while (NULL != (ae = nh->ae_head)) + { + GNUNET_CONTAINER_DLL_remove (nh->ae_head, + nh->ae_tail, + ae); + nh->address_callback (nh->callback_cls, + GNUNET_NO, + ae->ac, + (const struct sockaddr *) &ae[1], + ae->addrlen); + GNUNET_free (ae); + } nh->reconnect_delay = GNUNET_TIME_STD_BACKOFF (nh->reconnect_delay); nh->reconnect_task @@ -157,14 +176,7 @@ check_connection_reversal_request (void *cls, { if (ntohs (crm->header.size) != sizeof (*crm) + - ntohs (crm->local_addr_size) + - ntohs (crm->remote_addr_size) ) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if ( (sizeof (struct sockaddr_in) != ntohs (crm->local_addr_size)) || - (sizeof (struct sockaddr_in) != ntohs (crm->remote_addr_size)) ) + sizeof (struct sockaddr_in) ) { GNUNET_break (0); return GNUNET_SYSERR; @@ -172,7 +184,7 @@ check_connection_reversal_request (void *cls, return GNUNET_OK; } - + /** * Handle connection reversal request. * @@ -184,13 +196,9 @@ handle_connection_reversal_request (void *cls, const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm) { struct GNUNET_NAT_Handle *nh = cls; - const struct sockaddr_in *local_sa = (const struct sockaddr_in *) &crm[1]; - const struct sockaddr_in *remote_sa = &local_sa[1]; nh->reversal_callback (nh->callback_cls, - (const struct sockaddr *) local_sa, - sizeof (struct sockaddr_in), - (const struct sockaddr *) remote_sa, + (const struct sockaddr *) &crm[1], sizeof (struct sockaddr_in)); } @@ -239,7 +247,7 @@ check_address_change_notification (void *cls, return GNUNET_OK; } - + /** * Handle connection reversal request. * @@ -256,10 +264,13 @@ handle_address_change_notification (void *cls, enum GNUNET_NAT_AddressClass ac; struct AddrEntry *ae; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received address change notification\n"); ac = (enum GNUNET_NAT_AddressClass) ntohl (acn->addr_class); if (GNUNET_YES == ntohl (acn->add_remove)) { ae = GNUNET_malloc (sizeof (*ae) + alen); + ae->ac = ac; ae->addrlen = alen; GNUNET_memcpy (&ae[1], sa, @@ -334,7 +345,7 @@ do_connect (void *cls) struct GNUNET_MQ_Envelope *env; nh->reconnect_task = NULL; - nh->mq = GNUNET_CLIENT_connecT (nh->cfg, + nh->mq = GNUNET_CLIENT_connect (nh->cfg, "nat", handlers, &mq_error_handler, @@ -359,9 +370,8 @@ do_connect (void *cls) * address_callback for any 'plausible' external address. * * @param cfg configuration to use + * @param config_section name of the configuration section for optionsx * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP - * @param adv_port advertised port (port we are either bound to or that our OS - * locally performs redirection from to our bound port). * @param num_addrs number of addresses in @a addrs * @param addrs list of local addresses packets should be redirected to * @param addrlens actual lengths of the addresses in @a addrs @@ -373,8 +383,8 @@ do_connect (void *cls) */ struct GNUNET_NAT_Handle * GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *config_section, uint8_t proto, - uint16_t adv_port, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, @@ -385,12 +395,15 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_NAT_Handle *nh; struct GNUNET_NAT_RegisterMessage *rm; size_t len; + size_t str_len; char *off; - + len = 0; for (unsigned int i=0;i GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) || + str_len = strlen (config_section) + 1; + len += str_len; + if ( (len > GNUNET_MAX_MESSAGE_SIZE - sizeof (*rm)) || (num_addrs > UINT16_MAX) ) { GNUNET_break (0); @@ -405,7 +418,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, if (NULL != reversal_callback) rm->flags |= GNUNET_NAT_RF_REVERSAL; rm->proto = proto; - rm->adv_port = htons (adv_port); + rm->str_len = htons (str_len); rm->num_addrs = htons ((uint16_t) num_addrs); off = (char *) &rm[1]; for (unsigned int i=0;ireg = &rm->header; @@ -555,7 +575,7 @@ test_stun_packet (const void *data, * * The function does some basic sanity checks on packet size and * content, try to extract a bit of information. - * + * * At the moment this only processes BIND requests, and returns the * externally visible address of the request to the rest of the * NAT logic. @@ -649,7 +669,7 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh, * @param nh handle (used for configuration) * @param local_sa our local address of the peer (IPv4-only) * @param remote_sa the remote address of the peer (IPv4-only) - * @return #GNUNET_SYSERR on error, + * @return #GNUNET_SYSERR on error, * #GNUNET_NO if connection reversal is unavailable, * #GNUNET_OK otherwise (presumably in progress) */ @@ -664,6 +684,8 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh, if (NULL == nh->mq) return GNUNET_SYSERR; + GNUNET_break (AF_INET == local_sa->sin_family); + GNUNET_break (AF_INET == remote_sa->sin_family); env = GNUNET_MQ_msg_extra (req, 2 * sizeof (struct sockaddr_in), GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL); @@ -693,249 +715,19 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh, void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh) { - GNUNET_MQ_destroy (nh->mq); - GNUNET_free (nh->reg); - GNUNET_free (nh); -} - - - -/** - * Handle to auto-configuration in progress. - */ -struct GNUNET_NAT_AutoHandle -{ - - /** - * Configuration we use. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Message queue for communicating with the NAT service. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Function called with the result from the autoconfiguration. - */ - GNUNET_NAT_AutoResultCallback arc; - - /** - * Closure for @e arc. - */ - void *arc_cls; - -}; - - -/** - * Converts `enum GNUNET_NAT_StatusCode` to string - * - * @param err error code to resolve to a string - * @return point to a static string containing the error code - */ -const char * -GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err) -{ - switch (err) - { - case GNUNET_NAT_ERROR_SUCCESS: - return _ ("Operation Successful"); - case GNUNET_NAT_ERROR_IPC_FAILURE: - return _ ("IPC failure"); - case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR: - return _ ("Failure in network subsystem, check permissions."); - case GNUNET_NAT_ERROR_TIMEOUT: - return _ ("Encountered timeout while performing operation"); - case GNUNET_NAT_ERROR_NOT_ONLINE: - return _ ("detected that we are offline"); - case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND: - return _ ("`upnpc` command not found"); - case GNUNET_NAT_ERROR_UPNPC_FAILED: - return _ ("Failed to run `upnpc` command"); - case GNUNET_NAT_ERROR_UPNPC_TIMEOUT: - return _ ("`upnpc' command took too long, process killed"); - case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED: - return _ ("`upnpc' command failed to establish port mapping"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND: - return _ ("`external-ip' command not found"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: - return _ ("Failed to run `external-ip` command"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: - return _ ("`external-ip' command output invalid"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: - return _ ("no valid address was returned by `external-ip'"); - case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO: - return _ ("Could not determine interface with internal/local network address"); - case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND: - return _ ("No functioning gnunet-helper-nat-server installation found"); - case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED: - return _ ("NAT test could not be initialized"); - case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT: - return _ ("NAT test timeout reached"); - case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED: - return _ ("could not register NAT"); - case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND: - return _ ("No working gnunet-helper-nat-client installation found"); - default: - return "unknown status code"; - } -} - - -/** - * Check result from autoconfiguration attempt. - * - * @param cls the `struct GNUNET_NAT_AutoHandle` - * @param res the result - * @return #GNUNET_OK if @a res is well-formed (always for now) - */ -static int -check_auto_result (void *cls, - const struct GNUNET_NAT_AutoconfigResultMessage *res) -{ - return GNUNET_OK; -} - - -/** - * Handle result from autoconfiguration attempt. - * - * @param cls the `struct GNUNET_NAT_AutoHandle` - * @param res the result - */ -static void -handle_auto_result (void *cls, - const struct GNUNET_NAT_AutoconfigResultMessage *res) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - size_t left; - struct GNUNET_CONFIGURATION_Handle *cfg; - enum GNUNET_NAT_Type type - = (enum GNUNET_NAT_Type) ntohl (res->type); - enum GNUNET_NAT_StatusCode status - = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code); - - left = ntohs (res->header.size) - sizeof (*res); - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_deserialize (cfg, - (const char *) &res[1], - left, - GNUNET_NO)) - { - GNUNET_break (0); - ah->arc (ah->arc_cls, - NULL, - GNUNET_NAT_ERROR_IPC_FAILURE, - type); - } - else - { - ah->arc (ah->arc_cls, - cfg, - status, - type); - } - GNUNET_CONFIGURATION_destroy (cfg); - GNUNET_NAT_autoconfig_cancel (ah); -} - - -/** - * Handle queue errors by reporting autoconfiguration failure. - * - * @param cls the `struct GNUNET_NAT_AutoHandle *` - * @param error details about the error - */ -static void -ah_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - - ah->arc (ah->arc_cls, - NULL, - GNUNET_NAT_ERROR_IPC_FAILURE, - GNUNET_NAT_TYPE_UNKNOWN); - GNUNET_NAT_autoconfig_cancel (ah); -} - - -/** - * Start auto-configuration routine. The transport adapters should - * be stopped while this function is called. - * - * @param cfg initial configuration - * @param cb function to call with autoconfiguration result - * @param cb_cls closure for @a cb - * @return handle to cancel operation - */ -struct GNUNET_NAT_AutoHandle * -GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_NAT_AutoResultCallback cb, - void *cb_cls) -{ - struct GNUNET_NAT_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AutoHandle); - struct GNUNET_MQ_MessageHandler handlers[] = { - GNUNET_MQ_hd_var_size (auto_result, - GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT, - struct GNUNET_NAT_AutoconfigResultMessage, - ah), - GNUNET_MQ_handler_end () - }; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_NAT_AutoconfigRequestMessage *req; - char *buf; - size_t size; - - buf = GNUNET_CONFIGURATION_serialize (cfg, - &size); - if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req)) + if (NULL != nh->mq) { - GNUNET_break (0); - GNUNET_free (buf); - GNUNET_free (ah); - return NULL; + GNUNET_MQ_destroy (nh->mq); + nh->mq = NULL; } - ah->arc = cb; - ah->arc_cls = cb_cls; - ah->mq = GNUNET_CLIENT_connecT (cfg, - "nat", - handlers, - &ah_error_handler, - ah); - if (NULL == ah->mq) + if (NULL != nh->reconnect_task) { - GNUNET_break (0); - GNUNET_free (buf); - GNUNET_free (ah); - return NULL; + GNUNET_SCHEDULER_cancel (nh->reconnect_task); + nh->reconnect_task = NULL; } - env = GNUNET_MQ_msg_extra (req, - size, - GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG); - GNUNET_memcpy (&req[1], - buf, - size); - GNUNET_free (buf); - GNUNET_MQ_send (ah->mq, - env); - return ah; + GNUNET_free (nh->reg); + GNUNET_free (nh); } -/** - * Abort autoconfiguration. - * - * @param ah handle for operation to abort - */ -void -GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah) -{ - GNUNET_MQ_destroy (ah->mq); - GNUNET_free (ah); -} - /* end of nat_api.c */