improving NAT code
authorChristian Grothoff <christian@grothoff.org>
Wed, 29 Jun 2011 21:18:25 +0000 (21:18 +0000)
committerChristian Grothoff <christian@grothoff.org>
Wed, 29 Jun 2011 21:18:25 +0000 (21:18 +0000)
TODO
src/nat/gnunet-nat-client-windows.c
src/nat/gnunet-nat-client.c
src/nat/gnunet-nat-server-windows.c
src/nat/gnunet-nat-server.c
src/nat/nat.c
src/transport/gnunet-service-transport.c

diff --git a/TODO b/TODO
index 9bfde8893d1b7020462b9d51ece5709d46831773..99b091aca41651096a65b331c8803e61af0b0f11 100644 (file)
--- 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
     + 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)
 
   - 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]
index 2e7c8a86e4d0ccfd40cfa803fea53c9fd687581f..2fe3643ac1765aca69e308b9aaaadad60e78ebd1 100644 (file)
 */
 
 /**
- * @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
index 3e35aa8f4f50f77df5ad780f9e35b039d443ba4d..5f54f729b4f6a299772e0e4c50580af2a5d76555 100644 (file)
@@ -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
index 8cfad2ff297db6971d11f3c96d8bd070963232a2..6c4c7d7a12c3cac7901760a0895e06f257fb52ed 100644 (file)
@@ -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
index ab99b5f280d7f059ee4362e11b675d0b8983e413..ffc570146b801e43967e67a30737adf06c2f4f67 100644 (file)
@@ -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
index c4a4c75cbd14cc448633923af3f26ca6ef95eafe..e5a3e0e0f3e137fe22c1b27aa2135b3ceb043790 100644 (file)
  *
  * 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))
index 427b8dabdd7fde87386d5dab82921cc11b25534b..2e90bcf3e9f9d1706e8e17c67091f62504c4671c 100644 (file)
@@ -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);