gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] branch master updated: work towards supporting man


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated: work towards supporting manual hole punching in new NAT service
Date: Thu, 05 Jan 2017 13:50:19 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 89c7072  work towards supporting manual hole punching in new NAT 
service
     new aad1449  work towards supporting manual hole punching in new NAT 
service
89c7072 is described below

commit 89c7072fdc236c92fd7c252fb0efdc97fcb1367e
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Jan 5 13:49:57 2017 +0100

    work towards supporting manual hole punching in new NAT service
---
 src/include/gnunet_nat_service.h |   6 +
 src/nat/gnunet-service-nat.c     | 238 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 241 insertions(+), 3 deletions(-)

diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 1620c94..0dbc23e 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -123,6 +123,12 @@ enum GNUNET_NAT_AddressClass
   GNUNET_NAT_AC_EXTERN = 128,
 
   /**
+   * Addresses that were manually configured by the user.
+   * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL.
+   */
+  GNUNET_NAT_AC_MANUAL = 256,
+
+  /**
    * Bitmask for "any" address.
    */
   GNUNET_NAT_AC_ANY = 65535
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index e29f371..5037f52 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -44,6 +44,7 @@
 #include "gnunet_protocols.h"
 #include "gnunet_signatures.h"
 #include "gnunet_statistics_service.h"
+#include "gnunet_resolver_service.h"
 #include "gnunet_nat_service.h"
 #include "gnunet-service-nat_stun.h"
 #include "gnunet-service-nat_mini.h"
@@ -81,6 +82,11 @@
  */
 #define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 5)
 
+/**
+ * How often do we scan for changes in how our external (dyndns) hostname 
resolves?
+ */
+#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 7)
+
 
 /**
  * Information we track per client address. 
@@ -142,6 +148,33 @@ struct ClientHandle
    * have a hole punched).
    */
   char *hole_external;
+
+  /**
+   * Task for periodically re-running the @e ext_dns DNS lookup.
+   */ 
+  struct GNUNET_SCHEDULER_Task *ext_dns_task;
+  
+  /**
+   * Handle for (DYN)DNS lookup of our external IP as given in
+   * @e hole_external.
+   */
+  struct GNUNET_RESOLVER_RequestHandle *ext_dns;
+
+  /**
+   * External IP address as given in @e hole_external.
+   */
+  struct sockaddr_storage ext_addr;
+
+  /**
+   * Do we currently have a valid @e ext_addr which we told the
+   * client about? 
+   */
+  int ext_addr_set;
+
+  /**
+   * Port number we found in @e hole_external.
+   */ 
+  uint16_t ext_dns_port;
   
   /**
    * What does this client care about?
@@ -327,6 +360,11 @@ static struct AutoconfigContext *ac_tail;
 static struct GNUNET_TIME_Relative stun_stale_timeout;
 
 /**
+ * How often do we scan for changes in how our external (dyndns) hostname 
resolves?
+ */
+static struct GNUNET_TIME_Relative dyndns_frequency;
+
+/**
  * Handle to our current configuration.
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -765,7 +803,7 @@ check_notify_client (struct LocalAddressList *delta,
       const struct sockaddr_in *c4;
 
       if (AF_INET != ch->caddrs[i].ss.ss_family)
-       return; /* IPv4 not relevant */
+       continue; /* IPv4 not relevant */
       c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
       if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
           (0 != c4->sin_addr.s_addr) &&
@@ -808,7 +846,7 @@ check_notify_client (struct LocalAddressList *delta,
       const struct sockaddr_in6 *c6;
       
       if (AF_INET6 != ch->caddrs[i].ss.ss_family)
-       return; /* IPv4 not relevant */
+       continue; /* IPv4 not relevant */
       c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
       if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
           (0 != memcmp (&c6->sin6_addr,
@@ -1317,6 +1355,182 @@ upnp_addr_change_cb (void *cls,
 
 
 /**
+ * Resolve the `hole_external` name to figure out our 
+ * external address from a manually punched hole.  The
+ * port number has already been parsed, this task is 
+ * responsible for periodically doing a DNS lookup.
+ *
+ * @param ch client handle to act upon
+ */
+static void
+dyndns_lookup (void *cls);
+
+
+/**
+ * Our (external) hostname was resolved.  Update lists of
+ * current external IPs (note that DNS may return multiple
+ * addresses!) and notify client accordingly.
+ *
+ * @param cls the `struct ClientHandle`
+ * @param addr NULL on error, otherwise result of DNS lookup
+ * @param addrlen number of bytes in @a addr
+ */
+static void
+process_external_ip (void *cls,
+                     const struct sockaddr *addr,
+                     socklen_t addrlen)
+{
+  struct ClientHandle *ch = cls;
+
+  if (NULL == addr)
+  {
+    ch->ext_dns = NULL;
+    ch->ext_dns_task 
+      = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
+                                     &dyndns_lookup,
+                                     ch);
+    /* Current iteration is over, remove 'old' IPs now */
+    // FIXME: remove IPs we did NOT find!
+    GNUNET_break (0);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Got IP `%s' for external address `%s'\n",
+             GNUNET_a2s (addr,
+                         addrlen),
+             ch->hole_external);
+  // FIXME: notify client, and remember IP for later removal!
+}
+
+
+/**
+ * Resolve the `hole_external` name to figure out our 
+ * external address from a manually punched hole.  The
+ * port number has already been parsed, this task is 
+ * responsible for periodically doing a DNS lookup.
+ *
+ * @param ch client handle to act upon
+ */
+static void
+dyndns_lookup (void *cls)
+{
+  struct ClientHandle *ch = cls;
+
+  ch->ext_dns_task = NULL;
+  ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
+                                       AF_UNSPEC,
+                                       GNUNET_TIME_UNIT_MINUTES,
+                                       &process_external_ip,
+                                       ch);  
+}
+
+
+/**
+ * Resolve the `hole_external` name to figure out our 
+ * external address from a manually punched hole.  The
+ * given name may be "AUTO" in which case we should use
+ * the IP address(es) we have from upnpc or other methods.
+ * The name can also be an IP address, in which case we 
+ * do not need to do DNS resolution.  Finally, we also
+ * need to parse the port number.
+ *
+ * @param ch client handle to act upon
+ */
+static void
+lookup_hole_external (struct ClientHandle *ch)
+{
+  char *port;
+  unsigned int pnum;
+  struct sockaddr_in *s4;
+  struct LocalAddressList lal;
+    
+  port = strrchr (ch->hole_external, ':');
+  if (NULL == port)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Malformed punched hole specification `%s' (lacks port)\n"),
+               ch->hole_external);
+    return;
+  }
+  if ( (1 != sscanf (port + 1,
+                    "%u",
+                    &pnum)) ||
+       (pnum > 65535) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Invalid port number in punched hole specification `%s' 
(lacks port)\n"),
+               port + 1);
+    return;    
+  }
+  ch->ext_dns_port = (uint16_t) pnum;
+  *port = '\0';
+  if ('[' == *ch->hole_external)
+  {
+    struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ch->ext_addr;
+
+    memset (s6, 0, sizeof (*s6));
+    s6->sin6_family = AF_INET6;
+    if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Malformed punched hole specification `%s' (lacks `]')\n"),
+                 ch->hole_external);
+      return;
+    }
+    ch->hole_external[strlen(ch->hole_external)-1] = '\0';
+    if (1 != inet_pton (AF_INET6,
+                       ch->hole_external + 1,
+                       &s6->sin6_addr))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Malformed punched hole specification `%s' (IPv6 address 
invalid)"),
+                 ch->hole_external + 1);
+      return;
+    }
+    s6->sin6_port = htons (ch->ext_dns_port);
+    memset (&lal, 0, sizeof (lal));
+    GNUNET_memcpy (&lal.addr, s6, sizeof (*s6));
+    lal.af = AF_INET6;
+    lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+    check_notify_client (&lal,
+                        ch,
+                        GNUNET_YES);
+    ch->ext_addr_set = GNUNET_YES;
+    return;
+  } 
+  s4 = (struct sockaddr_in *) &ch->ext_addr;
+  memset (s4, 0, sizeof (*s4));
+  s4->sin_family = AF_INET;
+  if (1 == inet_pton (AF_INET,
+                     ch->hole_external,
+                     &s4->sin_addr))
+  {
+    s4->sin_port = htons (ch->ext_dns_port);
+    memset (&lal, 0, sizeof (lal));
+    GNUNET_memcpy (&lal.addr, s4, sizeof (*s4));
+    lal.af = AF_INET;
+    lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+    check_notify_client (&lal,
+                        ch,
+                        GNUNET_YES);
+    ch->ext_addr_set = GNUNET_YES;
+    return;
+  }
+  if (0 == strcasecmp (ch->hole_external,
+                      "AUTO"))
+  {
+    // FIXME: use `external-ip` address(es)!
+    GNUNET_break (0); // not implemented!
+    return;
+  }
+  /* got a DNS name, trigger lookup! */
+  ch->ext_dns_task
+    = GNUNET_SCHEDULER_add_now (&dyndns_lookup,
+                               ch);  
+}
+
+
+/**
  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
  * We remember the client for updates upon future NAT events.
  *
@@ -1422,7 +1636,9 @@ handle_register (void *cls,
   ch->hole_external
     = GNUNET_strndup (off,
                      ntohs (message->hole_external_len));
-    
+  if (0 != ntohs (message->hole_external_len))
+    lookup_hole_external (ch);
+  
   /* Actually send IP address list to client */
   for (struct LocalAddressList *lal = lal_head;
        NULL != lal;
@@ -2115,6 +2331,12 @@ run (void *cls,
       enable_upnp = GNUNET_SYSERR;
     }
   }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg,
+                                          "nat",
+                                          "DYNDNS_FREQUENCY",
+                                           &dyndns_frequency))
+    dyndns_frequency = DYNDNS_FREQUENCY;
   
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
                                 NULL);
@@ -2176,6 +2398,16 @@ client_disconnect_cb (void *cls,
     }
   }
   GNUNET_free_non_null (ch->caddrs);
+  if (NULL != ch->ext_dns_task)
+  {
+    GNUNET_SCHEDULER_cancel (ch->ext_dns_task);
+    ch->ext_dns_task = NULL;
+  }
+  if (NULL != ch->ext_dns)
+  {
+    GNUNET_RESOLVER_request_cancel (ch->ext_dns);
+    ch->ext_dns = NULL;
+  }
   GNUNET_free (ch->hole_external);
   GNUNET_free (ch);
 }

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]