From 503dbc5515ca5d4a590ab9378deb712236dd7a90 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 29 Jun 2011 21:18:25 +0000 Subject: improving NAT code --- TODO | 22 ++-- src/nat/gnunet-nat-client-windows.c | 6 +- src/nat/gnunet-nat-client.c | 2 +- src/nat/gnunet-nat-server-windows.c | 2 +- src/nat/gnunet-nat-server.c | 2 +- src/nat/nat.c | 169 +++++++++++++++++++++++++++---- src/transport/gnunet-service-transport.c | 37 ++++++- 7 files changed, 197 insertions(+), 43 deletions(-) diff --git a/TODO b/TODO index 9bfde8893..99b091aca 100644 --- a/TODO +++ b/TODO @@ -1,17 +1,15 @@ 0.9.0pre3: * clean buildbots -0.9.0: -* new webpage: - - write chapter on DHT/block [Nate] - - make a NICE download page -* NAT/UPNP: [CG/MW] - - write NAT library +0.9.0pre4: +* NAT library: [CG/MW] + - UPnP support + - testcase + - more testing * Transport: - UDP fragmentation [MW] - decide how to deal with 'DISABLEV6' option (where does it live?) - integration of new NAT/plugin API with HTTP/HTTPS plugin - - fix WLAN plugin for new plugin API (easy) - testing (again) * GNUNET-GTK: [CG] - figure out where in the GUI we should show active upload operations and allow aborts @@ -24,6 +22,11 @@ + insert + download + search + +0.9.0: +* new webpage: + - write chapter on DHT/block [Nate] + - make a NICE download page * big code review * Determine RC bugs and fix those (release should have no known real bugs) @@ -71,11 +74,6 @@ - better tracking of which config changes actually need to cause process restarts by ARM. - handle gnunet-arm -k in combination with auto-start magic (what is the right thing here?) - discover dependencies between services -* MONKEY: [Safey] - - better crash management (attach debugging support, capture and analyze - debug output, detect random vs. deterministic crashes) - - '-m EMAIL' option for alternative e-mail TO - - '-f FILENAME' option to write report to file instead of e-mail (for testing!) 0.9.2: * PEERINFO: [NN] diff --git a/src/nat/gnunet-nat-client-windows.c b/src/nat/gnunet-nat-client-windows.c index 2e7c8a86e..2fe3643ac 100644 --- a/src/nat/gnunet-nat-client-windows.c +++ b/src/nat/gnunet-nat-client-windows.c @@ -19,10 +19,10 @@ */ /** - * @file src/transport/gnunet-nat-client-windows.c + * @file src/nat/gnunet-nat-client-windows.c * @brief Tool to help bypass NATs using ICMP method; must run as - * root (SUID will do) or administrator on W32 - * This code will work under GNU/Linux or W32. + * administrator on W32 + * This code is forx W32. * @author Nathan Evans * * This program will send ONE ICMP message using RAW sockets diff --git a/src/nat/gnunet-nat-client.c b/src/nat/gnunet-nat-client.c index 3e35aa8f4..5f54f729b 100644 --- a/src/nat/gnunet-nat-client.c +++ b/src/nat/gnunet-nat-client.c @@ -19,7 +19,7 @@ */ /** - * @file src/transport/gnunet-nat-client.c + * @file src/nat/gnunet-nat-client.c * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) * This code will work under GNU/Linux only. * @author Christian Grothoff diff --git a/src/nat/gnunet-nat-server-windows.c b/src/nat/gnunet-nat-server-windows.c index 8cfad2ff2..6c4c7d7a1 100644 --- a/src/nat/gnunet-nat-server-windows.c +++ b/src/nat/gnunet-nat-server-windows.c @@ -19,7 +19,7 @@ */ /** - * @file src/transport/gnunet-nat-server-windows.c + * @file src/nat/gnunet-nat-server-windows.c * @brief Windows tool to help bypass NATs using ICMP method * This code will work under W32 only * @author Christian Grothoff diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c index ab99b5f28..ffc570146 100644 --- a/src/nat/gnunet-nat-server.c +++ b/src/nat/gnunet-nat-server.c @@ -19,7 +19,7 @@ */ /** - * @file src/transport/gnunet-nat-server.c + * @file src/nat/gnunet-nat-server.c * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) * This code will work under GNU/Linux only (or maybe BSDs, but never W32) * @author Christian Grothoff diff --git a/src/nat/nat.c b/src/nat/nat.c index c4a4c75cb..e5a3e0e0f 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c @@ -27,13 +27,32 @@ * * TODO: * - implement UPnP/PMP support - * - repeatedly perform certain checks again to notice changes + * - make frequency of checks configurable */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "gnunet_nat_lib.h" +/** + * How often do we scan for changes in our IP address from our local + * interfaces? + * FIXME: make this configurable... + */ +#define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) + +/** + * How often do we scan for changes in how our hostname resolves? + * FIXME: make this configurable... + */ +#define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20) + + +/** + * How often do we scan for changes in how our external (dyndns) hostname resolves? + * FIXME: make this configurable... + */ +#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) /** * How long until we give up on transmitting the welcome message? @@ -52,20 +71,17 @@ enum LocalAddressSource /** * Address was obtained by DNS resolution of the external hostname * given in the configuration (i.e. hole-punched DynDNS setup). - * FIXME: repeatedly do the lookup to notice changes! */ LAL_EXTERNAL_IP, /** * Address was obtained by looking up our own hostname in DNS. - * FIXME: repeatedly do the lookup to notice changes! */ LAL_HOSTNAME_DNS, /** * Address was obtained by scanning our hosts's network interfaces * and taking their address (no DNS involved). - * FIXME: repeatedly do the lookup to notice changes! */ LAL_INTERFACE_ADDRESS, @@ -182,6 +198,16 @@ struct GNUNET_NAT_Handle */ GNUNET_SCHEDULER_TaskIdentifier ifc_task; + /** + * ID of hostname DNS lookup task + */ + GNUNET_SCHEDULER_TaskIdentifier hostname_task; + + /** + * ID of DynDNS lookup task + */ + GNUNET_SCHEDULER_TaskIdentifier dns_task; + /** * The process id of the server process (if behind NAT) */ @@ -270,6 +296,38 @@ static void start_gnunet_nat_server (struct GNUNET_NAT_Handle *h); +/** + * Remove all addresses from the list of 'local' addresses + * that originated from the given source. + * + * @param plugin the plugin + * @param src source that identifies addresses to remove + */ +static void +remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h, + enum LocalAddressSource src) +{ + struct LocalAddressList *pos; + struct LocalAddressList *next; + + next = h->lal_head; + while (NULL != (pos = next)) + { + next = pos->next; + if (pos->source != src) + continue; + GNUNET_CONTAINER_DLL_remove (h->lal_head, + h->lal_tail, + pos); + h->address_callback (h->callback_cls, + GNUNET_NO, + (const struct sockaddr* ) &pos[1], + pos->addrlen); + GNUNET_free (pos); + } +} + + /** * Add the given address to the list of 'local' addresses, thereby * making it a 'legal' address for this peer to have. @@ -437,6 +495,18 @@ add_ip_to_address_list (struct GNUNET_NAT_Handle *h, } +/** + * Task to do DNS lookup on our external hostname to + * get DynDNS-IP addresses. + * + * @param cls the NAT handle + * @param tc scheduler context + */ +static void +resolve_dns (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + /** * Our (external) hostname was resolved and the configuration says that * the NAT was hole-punched. @@ -455,15 +525,25 @@ process_external_ip (void *cls, if (addr == NULL) { h->ext_dns = NULL; - /* FIXME: schedule task to resolve IP again in the - future, and if the result changes, update the - local address list accordingly */ + h->dns_task = GNUNET_SCHEDULER_add_delayed (DYNDNS_FREQUENCY, + &resolve_dns, h); return; } add_to_address_list (h, LAL_EXTERNAL_IP, addr, addrlen); } +/** + * Task to do a lookup on our hostname for IP addresses. + * + * @param cls the NAT handle + * @param tc scheduler context + */ +static void +resolve_hostname (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + /** * Function called by the resolver for each address obtained from DNS * for our own hostname. Add the addresses to the list of our IP @@ -482,9 +562,8 @@ process_hostname_ip (void *cls, if (addr == NULL) { h->hostname_dns = NULL; - /* FIXME: schedule task to resolve IP again in the - future, and if the result changes, update the - address list accordingly */ + h->hostname_task = GNUNET_SCHEDULER_add_delayed (HOSTNAME_DNS_FREQUENCY, + &resolve_hostname, h); return; } add_to_address_list (h, LAL_HOSTNAME_DNS, addr, addrlen); @@ -874,11 +953,54 @@ list_interfaces (void *cls, struct GNUNET_NAT_Handle *h = cls; h->ifc_task = GNUNET_SCHEDULER_NO_TASK; + remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS); GNUNET_OS_network_interfaces_list (&process_interfaces, h); -#if 0 - h->ifc_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FIXME, + h->ifc_task = GNUNET_SCHEDULER_add_delayed (IFC_SCAN_FREQUENCY, &list_interfaces, h); -#endif +} + + +/** + * Task to do a lookup on our hostname for IP addresses. + * + * @param cls the NAT handle + * @param tc scheduler context + */ +static void +resolve_hostname (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_NAT_Handle *h = cls; + + h->hostname_task = GNUNET_SCHEDULER_NO_TASK; + remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS); + h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, + HOSTNAME_RESOLVE_TIMEOUT, + &process_hostname_ip, + h); +} + + +/** + * Task to do DNS lookup on our external hostname to + * get DynDNS-IP addresses. + * + * @param cls the NAT handle + * @param tc scheduler context + */ +static void +resolve_dns (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_NAT_Handle *h = cls; + + h->dns_task = GNUNET_SCHEDULER_NO_TASK; + remove_from_address_list_by_source (h, LAL_EXTERNAL_IP); + h->ext_dns = GNUNET_RESOLVER_ip_get (h->external_address, + AF_INET, + GNUNET_TIME_UNIT_MINUTES, + &process_external_ip, + h); } @@ -1014,11 +1136,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, (h->external_address != NULL) && (h->nat_punched == GNUNET_YES) ) { - h->ext_dns = GNUNET_RESOLVER_ip_get (h->external_address, - AF_INET, - GNUNET_TIME_UNIT_MINUTES, - &process_external_ip, - h); + h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h); h->enable_nat_server = GNUNET_NO; h->enable_upnp = GNUNET_NO; } @@ -1049,10 +1167,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, if (NULL != h->address_callback) { h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces, h); - h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, - HOSTNAME_RESOLVE_TIMEOUT, - &process_hostname_ip, - h); + h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname, h); } return h; } @@ -1090,6 +1205,16 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) GNUNET_SCHEDULER_cancel (h->ifc_task); h->ifc_task = GNUNET_SCHEDULER_NO_TASK; } + if (GNUNET_SCHEDULER_NO_TASK != h->hostname_task) + { + GNUNET_SCHEDULER_cancel (h->hostname_task); + h->hostname_task = GNUNET_SCHEDULER_NO_TASK; + } + if (GNUNET_SCHEDULER_NO_TASK != h->dns_task) + { + GNUNET_SCHEDULER_cancel (h->dns_task); + h->dns_task = GNUNET_SCHEDULER_NO_TASK; + } if (NULL != h->server_proc) { if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM)) diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 427b8dabd..2e90bcf3e 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -1217,6 +1217,11 @@ static struct GNUNET_CONTAINER_MultiHashMap *validation_map; */ static struct GNUNET_STATISTICS_Handle *stats; +/** + * Identifier of 'refresh_hello' task. + */ +static GNUNET_SCHEDULER_TaskIdentifier hello_task; + /** * Is transport service shutting down ? */ @@ -2448,15 +2453,20 @@ address_generator (void *cls, size_t max, void *buf) /** * Construct our HELLO message from all of the addresses of * all of the transports. + * + * @param cls unused + * @param tc scheduler context */ static void -refresh_hello () +refresh_hello_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HELLO_Message *hello; struct TransportClient *cpos; struct NeighbourList *npos; struct GeneratorContext gc; + hello_task = GNUNET_SCHEDULER_NO_TASK; gc.plug_pos = plugins; gc.addr_pos = plugins != NULL ? plugins->addresses : NULL; gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); @@ -2503,6 +2513,21 @@ refresh_hello () } +/** + * Schedule task to refresh hello (unless such a + * task exists already). + */ +static void +refresh_hello () +{ + if (hello_task != GNUNET_SCHEDULER_NO_TASK) + return; + hello_task + = GNUNET_SCHEDULER_add_now (&refresh_hello_task, + NULL); +} + + /** * Iterator over hash map entries that NULLs the session of validation * entries that match the given session. @@ -4548,7 +4573,7 @@ transmit_hello_and_ping (void *cls, return; } if (NULL == our_hello) - refresh_hello (); + refresh_hello_task (NULL, NULL); hello_size = GNUNET_HELLO_size(our_hello); slen = strlen(va->transport_name) + 1; tsize = sizeof(struct TransportPingMessage) + hello_size + va->addrlen + slen; @@ -6302,6 +6327,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_PEERINFO_disconnect (peerinfo); peerinfo = NULL; } + if (GNUNET_SCHEDULER_NO_TASK != hello_task) + { + GNUNET_SCHEDULER_cancel (hello_task); + hello_task = GNUNET_SCHEDULER_NO_TASK; + } /* Can we assume those are gone by now, or do we need to clean up explicitly!? */ GNUNET_break (bl_head == NULL); @@ -7743,7 +7773,8 @@ run (void *cls, ats_init(); #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n")); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Transport service ready.\n")); #endif /* If we have a blacklist file, read from it */ read_blacklist_file(cfg); -- cgit v1.2.3