diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-06 13:26:38 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-06 13:26:38 +0100 |
commit | 80e1315b56f559db60499f5373e90c293c5ab065 (patch) | |
tree | 3b279e6ac8e6298d7d9d96d12868f628a413939b /src/nat/gnunet-service-nat.c | |
parent | 1b7f6eea0a06abab9b75b30f021aa6313fccfcd4 (diff) | |
download | gnunet-80e1315b56f559db60499f5373e90c293c5ab065.tar.gz gnunet-80e1315b56f559db60499f5373e90c293c5ab065.zip |
separate service for autoconfiguration from NAT traversal
Diffstat (limited to 'src/nat/gnunet-service-nat.c')
-rw-r--r-- | src/nat/gnunet-service-nat.c | 355 |
1 files changed, 0 insertions, 355 deletions
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 | |||
@@ -284,80 +284,6 @@ struct StunExternalIP | |||
284 | 284 | ||
285 | 285 | ||
286 | /** | 286 | /** |
287 | * Context for autoconfiguration operations. | ||
288 | */ | ||
289 | struct AutoconfigContext | ||
290 | { | ||
291 | /** | ||
292 | * Kept in a DLL. | ||
293 | */ | ||
294 | struct AutoconfigContext *prev; | ||
295 | |||
296 | /** | ||
297 | * Kept in a DLL. | ||
298 | */ | ||
299 | struct AutoconfigContext *next; | ||
300 | |||
301 | /** | ||
302 | * Which client asked the question. | ||
303 | */ | ||
304 | struct ClientHandle *ch; | ||
305 | |||
306 | /** | ||
307 | * Configuration we are creating. | ||
308 | */ | ||
309 | struct GNUNET_CONFIGURATION_Handle *c; | ||
310 | |||
311 | /** | ||
312 | * Original configuration (for diffing). | ||
313 | */ | ||
314 | struct GNUNET_CONFIGURATION_Handle *orig; | ||
315 | |||
316 | /** | ||
317 | * Timeout task to force termination. | ||
318 | */ | ||
319 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
320 | |||
321 | /** | ||
322 | * What type of system are we on? | ||
323 | */ | ||
324 | char *system_type; | ||
325 | |||
326 | /** | ||
327 | * Handle to activity to probe for our external IP. | ||
328 | */ | ||
329 | struct GNUNET_NAT_ExternalHandle *probe_external; | ||
330 | |||
331 | /** | ||
332 | * #GNUNET_YES if upnpc should be used, | ||
333 | * #GNUNET_NO if upnpc should not be used, | ||
334 | * #GNUNET_SYSERR if we should simply not change the option. | ||
335 | */ | ||
336 | int enable_upnpc; | ||
337 | |||
338 | /** | ||
339 | * Status code to return to the client. | ||
340 | */ | ||
341 | enum GNUNET_NAT_StatusCode status_code; | ||
342 | |||
343 | /** | ||
344 | * NAT type to return to the client. | ||
345 | */ | ||
346 | enum GNUNET_NAT_Type type; | ||
347 | }; | ||
348 | |||
349 | |||
350 | /** | ||
351 | * DLL of our autoconfiguration operations. | ||
352 | */ | ||
353 | static struct AutoconfigContext *ac_head; | ||
354 | |||
355 | /** | ||
356 | * DLL of our autoconfiguration operations. | ||
357 | */ | ||
358 | static struct AutoconfigContext *ac_tail; | ||
359 | |||
360 | /** | ||
361 | * Timeout to use when STUN data is considered stale. | 287 | * Timeout to use when STUN data is considered stale. |
362 | */ | 288 | */ |
363 | static struct GNUNET_TIME_Relative stun_stale_timeout; | 289 | static struct GNUNET_TIME_Relative stun_stale_timeout; |
@@ -1920,274 +1846,6 @@ handle_request_connection_reversal (void *cls, | |||
1920 | 1846 | ||
1921 | 1847 | ||
1922 | /** | 1848 | /** |
1923 | * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message | ||
1924 | * from client. | ||
1925 | * | ||
1926 | * @param cls client who sent the message | ||
1927 | * @param message the message received | ||
1928 | * @return #GNUNET_OK if message is well-formed | ||
1929 | */ | ||
1930 | static int | ||
1931 | check_autoconfig_request (void *cls, | ||
1932 | const struct GNUNET_NAT_AutoconfigRequestMessage *message) | ||
1933 | { | ||
1934 | return GNUNET_OK; /* checked later */ | ||
1935 | } | ||
1936 | |||
1937 | |||
1938 | /** | ||
1939 | * Stop all pending activities with respect to the @a ac | ||
1940 | * | ||
1941 | * @param ac autoconfiguration to terminate activities for | ||
1942 | */ | ||
1943 | static void | ||
1944 | terminate_ac_activities (struct AutoconfigContext *ac) | ||
1945 | { | ||
1946 | if (NULL != ac->probe_external) | ||
1947 | { | ||
1948 | GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external); | ||
1949 | ac->probe_external = NULL; | ||
1950 | } | ||
1951 | if (NULL != ac->timeout_task) | ||
1952 | { | ||
1953 | GNUNET_SCHEDULER_cancel (ac->timeout_task); | ||
1954 | ac->timeout_task = NULL; | ||
1955 | } | ||
1956 | } | ||
1957 | |||
1958 | |||
1959 | /** | ||
1960 | * Finish handling the autoconfiguration request and send | ||
1961 | * the response to the client. | ||
1962 | * | ||
1963 | * @param cls the `struct AutoconfigContext` to conclude | ||
1964 | */ | ||
1965 | static void | ||
1966 | conclude_autoconfig_request (void *cls) | ||
1967 | { | ||
1968 | struct AutoconfigContext *ac = cls; | ||
1969 | struct ClientHandle *ch = ac->ch; | ||
1970 | struct GNUNET_NAT_AutoconfigResultMessage *arm; | ||
1971 | struct GNUNET_MQ_Envelope *env; | ||
1972 | size_t c_size; | ||
1973 | char *buf; | ||
1974 | struct GNUNET_CONFIGURATION_Handle *diff; | ||
1975 | |||
1976 | ac->timeout_task = NULL; | ||
1977 | terminate_ac_activities (ac); | ||
1978 | |||
1979 | /* Send back response */ | ||
1980 | diff = GNUNET_CONFIGURATION_get_diff (ac->orig, | ||
1981 | ac->c); | ||
1982 | buf = GNUNET_CONFIGURATION_serialize (diff, | ||
1983 | &c_size); | ||
1984 | GNUNET_CONFIGURATION_destroy (diff); | ||
1985 | env = GNUNET_MQ_msg_extra (arm, | ||
1986 | c_size, | ||
1987 | GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT); | ||
1988 | arm->status_code = htonl ((uint32_t) ac->status_code); | ||
1989 | arm->type = htonl ((uint32_t) ac->type); | ||
1990 | GNUNET_memcpy (&arm[1], | ||
1991 | buf, | ||
1992 | c_size); | ||
1993 | GNUNET_free (buf); | ||
1994 | GNUNET_MQ_send (ch->mq, | ||
1995 | env); | ||
1996 | |||
1997 | /* clean up */ | ||
1998 | GNUNET_free (ac->system_type); | ||
1999 | GNUNET_CONFIGURATION_destroy (ac->orig); | ||
2000 | GNUNET_CONFIGURATION_destroy (ac->c); | ||
2001 | GNUNET_CONTAINER_DLL_remove (ac_head, | ||
2002 | ac_tail, | ||
2003 | ac); | ||
2004 | GNUNET_free (ac); | ||
2005 | GNUNET_SERVICE_client_continue (ch->client); | ||
2006 | } | ||
2007 | |||
2008 | |||
2009 | /** | ||
2010 | * Check if all autoconfiguration operations have concluded, | ||
2011 | * and if they have, send the result back to the client. | ||
2012 | * | ||
2013 | * @param ac autoconfiguation context to check | ||
2014 | */ | ||
2015 | static void | ||
2016 | check_autoconfig_finished (struct AutoconfigContext *ac) | ||
2017 | { | ||
2018 | if (NULL != ac->probe_external) | ||
2019 | return; | ||
2020 | GNUNET_SCHEDULER_cancel (ac->timeout_task); | ||
2021 | ac->timeout_task | ||
2022 | = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request, | ||
2023 | ac); | ||
2024 | } | ||
2025 | |||
2026 | |||
2027 | /** | ||
2028 | * Update ENABLE_UPNPC configuration option. | ||
2029 | * | ||
2030 | * @param ac autoconfiguration to update | ||
2031 | */ | ||
2032 | static void | ||
2033 | update_enable_upnpc_option (struct AutoconfigContext *ac) | ||
2034 | { | ||
2035 | switch (ac->enable_upnpc) | ||
2036 | { | ||
2037 | case GNUNET_YES: | ||
2038 | GNUNET_CONFIGURATION_set_value_string (ac->c, | ||
2039 | "NAT", | ||
2040 | "ENABLE_UPNP", | ||
2041 | "YES"); | ||
2042 | break; | ||
2043 | case GNUNET_NO: | ||
2044 | GNUNET_CONFIGURATION_set_value_string (ac->c, | ||
2045 | "NAT", | ||
2046 | "ENABLE_UPNP", | ||
2047 | "NO"); | ||
2048 | break; | ||
2049 | case GNUNET_SYSERR: | ||
2050 | /* We are unsure, do not change option */ | ||
2051 | break; | ||
2052 | } | ||
2053 | } | ||
2054 | |||
2055 | |||
2056 | /** | ||
2057 | * Handle result from external IP address probe during | ||
2058 | * autoconfiguration. | ||
2059 | * | ||
2060 | * @param cls our `struct AutoconfigContext` | ||
2061 | * @param addr the address, NULL on errors | ||
2062 | * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code | ||
2063 | */ | ||
2064 | static void | ||
2065 | auto_external_result_cb (void *cls, | ||
2066 | const struct in_addr *addr, | ||
2067 | enum GNUNET_NAT_StatusCode result) | ||
2068 | { | ||
2069 | struct AutoconfigContext *ac = cls; | ||
2070 | |||
2071 | ac->probe_external = NULL; | ||
2072 | switch (result) | ||
2073 | { | ||
2074 | case GNUNET_NAT_ERROR_SUCCESS: | ||
2075 | ac->enable_upnpc = GNUNET_YES; | ||
2076 | break; | ||
2077 | case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: | ||
2078 | case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: | ||
2079 | case GNUNET_NAT_ERROR_IPC_FAILURE: | ||
2080 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2081 | "Disabling UPNPC: %d\n", | ||
2082 | (int) result); | ||
2083 | ac->enable_upnpc = GNUNET_NO; /* did not work */ | ||
2084 | break; | ||
2085 | default: | ||
2086 | GNUNET_break (0); /* unexpected */ | ||
2087 | ac->enable_upnpc = GNUNET_SYSERR; | ||
2088 | break; | ||
2089 | } | ||
2090 | update_enable_upnpc_option (ac); | ||
2091 | check_autoconfig_finished (ac); | ||
2092 | } | ||
2093 | |||
2094 | |||
2095 | /** | ||
2096 | * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from | ||
2097 | * client. | ||
2098 | * | ||
2099 | * @param cls client who sent the message | ||
2100 | * @param message the message received | ||
2101 | */ | ||
2102 | static void | ||
2103 | handle_autoconfig_request (void *cls, | ||
2104 | const struct GNUNET_NAT_AutoconfigRequestMessage *message) | ||
2105 | { | ||
2106 | struct ClientHandle *ch = cls; | ||
2107 | size_t left = ntohs (message->header.size) - sizeof (*message); | ||
2108 | struct LocalAddressList *lal; | ||
2109 | struct AutoconfigContext *ac; | ||
2110 | |||
2111 | ac = GNUNET_new (struct AutoconfigContext); | ||
2112 | ac->status_code = GNUNET_NAT_ERROR_SUCCESS; | ||
2113 | ac->ch = ch; | ||
2114 | ac->c = GNUNET_CONFIGURATION_create (); | ||
2115 | if (GNUNET_OK != | ||
2116 | GNUNET_CONFIGURATION_deserialize (ac->c, | ||
2117 | (const char *) &message[1], | ||
2118 | left, | ||
2119 | GNUNET_NO)) | ||
2120 | { | ||
2121 | GNUNET_break (0); | ||
2122 | GNUNET_SERVICE_client_drop (ch->client); | ||
2123 | GNUNET_CONFIGURATION_destroy (ac->c); | ||
2124 | GNUNET_free (ac); | ||
2125 | return; | ||
2126 | } | ||
2127 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2128 | "Received REQUEST_AUTO_CONFIG message from client\n"); | ||
2129 | |||
2130 | if (GNUNET_OK != | ||
2131 | GNUNET_CONFIGURATION_get_value_string (ac->c, | ||
2132 | "PEER", | ||
2133 | "SYSTEM_TYPE", | ||
2134 | &ac->system_type)) | ||
2135 | ac->system_type = GNUNET_strdup ("UNKNOWN"); | ||
2136 | |||
2137 | GNUNET_CONTAINER_DLL_insert (ac_head, | ||
2138 | ac_tail, | ||
2139 | ac); | ||
2140 | ac->orig | ||
2141 | = GNUNET_CONFIGURATION_dup (ac->c); | ||
2142 | ac->timeout_task | ||
2143 | = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT, | ||
2144 | &conclude_autoconfig_request, | ||
2145 | ac); | ||
2146 | ac->enable_upnpc = GNUNET_SYSERR; /* undecided */ | ||
2147 | |||
2148 | /* Probe for upnpc */ | ||
2149 | if (GNUNET_SYSERR == | ||
2150 | GNUNET_OS_check_helper_binary ("upnpc", | ||
2151 | GNUNET_NO, | ||
2152 | NULL)) | ||
2153 | { | ||
2154 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2155 | _("UPnP client `upnpc` command not found, disabling UPnP\n")); | ||
2156 | ac->enable_upnpc = GNUNET_NO; | ||
2157 | } | ||
2158 | else | ||
2159 | { | ||
2160 | for (lal = lal_head; NULL != lal; lal = lal->next) | ||
2161 | if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN)) | ||
2162 | /* we are behind NAT, useful to try upnpc */ | ||
2163 | ac->enable_upnpc = GNUNET_YES; | ||
2164 | } | ||
2165 | if (GNUNET_YES == ac->enable_upnpc) | ||
2166 | { | ||
2167 | /* If we are a mobile device, always leave it on as the network | ||
2168 | may change to one that supports UPnP anytime. If we are | ||
2169 | stationary, check if our network actually supports UPnP, and if | ||
2170 | not, disable it. */ | ||
2171 | if ( (0 == strcasecmp (ac->system_type, | ||
2172 | "INFRASTRUCTURE")) || | ||
2173 | (0 == strcasecmp (ac->system_type, | ||
2174 | "DESKTOP")) ) | ||
2175 | { | ||
2176 | /* Check if upnpc gives us an external IP */ | ||
2177 | ac->probe_external | ||
2178 | = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb, | ||
2179 | ac); | ||
2180 | } | ||
2181 | } | ||
2182 | if (NULL == ac->probe_external) | ||
2183 | update_enable_upnpc_option (ac); | ||
2184 | |||
2185 | /* Finally, check if we are already done */ | ||
2186 | check_autoconfig_finished (ac); | ||
2187 | } | ||
2188 | |||
2189 | |||
2190 | /** | ||
2191 | * Task run during shutdown. | 1849 | * Task run during shutdown. |
2192 | * | 1850 | * |
2193 | * @param cls unused | 1851 | * @param cls unused |
@@ -2196,16 +1854,7 @@ static void | |||
2196 | shutdown_task (void *cls) | 1854 | shutdown_task (void *cls) |
2197 | { | 1855 | { |
2198 | struct StunExternalIP *se; | 1856 | struct StunExternalIP *se; |
2199 | struct AutoconfigContext *ac; | ||
2200 | 1857 | ||
2201 | while (NULL != (ac = ac_head)) | ||
2202 | { | ||
2203 | GNUNET_CONTAINER_DLL_remove (ac_head, | ||
2204 | ac_tail, | ||
2205 | ac); | ||
2206 | terminate_ac_activities (ac); | ||
2207 | GNUNET_free (ac); | ||
2208 | } | ||
2209 | while (NULL != (se = se_head)) | 1858 | while (NULL != (se = se_head)) |
2210 | { | 1859 | { |
2211 | GNUNET_CONTAINER_DLL_remove (se_head, | 1860 | GNUNET_CONTAINER_DLL_remove (se_head, |
@@ -2386,10 +2035,6 @@ GNUNET_SERVICE_MAIN | |||
2386 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, | 2035 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, |
2387 | struct GNUNET_NAT_RequestConnectionReversalMessage, | 2036 | struct GNUNET_NAT_RequestConnectionReversalMessage, |
2388 | NULL), | 2037 | NULL), |
2389 | GNUNET_MQ_hd_var_size (autoconfig_request, | ||
2390 | GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG, | ||
2391 | struct GNUNET_NAT_AutoconfigRequestMessage, | ||
2392 | NULL), | ||
2393 | GNUNET_MQ_handler_end ()); | 2038 | GNUNET_MQ_handler_end ()); |
2394 | 2039 | ||
2395 | 2040 | ||