gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [gnunet] branch master updated (6c60f59 -> 28e8a15)


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated (6c60f59 -> 28e8a15)
Date: Sun, 18 Dec 2016 07:38:16 +0100

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

grothoff pushed a change to branch master
in repository gnunet.

    from 6c60f59  finish external-ip client notification, but not yet tested
     new bc4a5ae  implement writing of configuration file in autoconfiguration
     new 605227e  properly process external IP addresses from upnpc-based hole 
punching
     new 28e8a15  update todos

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 doc/man/gnunet-nat.1                   |   4 +
 src/include/gnunet_configuration_lib.h |   2 +-
 src/nat/gnunet-nat.c                   |  92 ++++++++++++++++--
 src/nat/gnunet-service-nat.c           | 165 +++++++++++++++++++++++++++------
 src/nat/gnunet-service-nat_mini.c      |  21 +++--
 5 files changed, 241 insertions(+), 43 deletions(-)

diff --git a/doc/man/gnunet-nat.1 b/doc/man/gnunet-nat.1
index a43223f..9cc8b12 100644
--- a/doc/man/gnunet-nat.1
+++ b/doc/man/gnunet-nat.1
@@ -58,6 +58,10 @@ Use TCP.
 .IP "\-u,  \-\-udp"
 Use UDP.
 
+.B
+.IP "\-w,  \-\-write"
+Write configuration to configuration file, useful in combination with 
autoconfiguration (\-a).
+
 .SH BUGS
 Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending 
electronic mail to <address@hidden>
 
diff --git a/src/include/gnunet_configuration_lib.h 
b/src/include/gnunet_configuration_lib.h
index 945f3ca..746dea6 100644
--- a/src/include/gnunet_configuration_lib.h
+++ b/src/include/gnunet_configuration_lib.h
@@ -89,7 +89,7 @@ GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle 
*cfg,
 
 /**
  * Load default configuration.  This function will parse the
- * defaults from the given defaults_d directory.
+ * defaults from the given @a defaults_d directory.
  *
  * @param cfg configuration to update
  * @param defaults_d directory with the defaults
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 7d10167..f3e26ff 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -59,6 +59,22 @@ static int listen_reversal;
 static int use_tcp;
 
 /**
+ * If we do auto-configuration, should we write the result
+ * to a file?
+ */
+static int write_cfg;
+
+/**
+ * Configuration filename.
+ */ 
+static const char *cfg_file;
+
+/**
+ * Original configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
  * Protocol to use.
  */
 static uint8_t proto;
@@ -149,9 +165,16 @@ auto_conf_iter (void *cls,
                 const char *option,
                 const char *value)
 {
+  struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
+  
   PRINTF ("%s: %s\n",
          option,
          value);
+  if (NULL != new_cfg)
+    GNUNET_CONFIGURATION_set_value_string (new_cfg,
+                                          section,
+                                          option,
+                                          value);
 }
 
 
@@ -172,6 +195,7 @@ auto_config_cb (void *cls,
 {
   const char *nat_type;
   char unknown_type[64];
+  struct GNUNET_CONFIGURATION_Handle *new_cfg;
 
   ah = NULL;
   switch (type)
@@ -196,19 +220,69 @@ auto_config_cb (void *cls,
     break;
   }
 
-  PRINTF ("NAT status: %s/%s\n",
-         GNUNET_NAT_status2string (result),
-         nat_type);
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+             "NAT status: %s/%s\n",
+             GNUNET_NAT_status2string (result),
+             nat_type);
+
+  /* Shortcut: if there are no changes suggested, bail out early. */
+  if (GNUNET_NO ==
+      GNUNET_CONFIGURATION_is_dirty (diff))
+  {
+    test_finished ();
+    return;
+  }
 
+  /* Apply diff to original configuration and show changes
+     to the user */
+  new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
+  
   if (NULL != diff)
   {
-    PRINTF ("SUGGESTED CHANGES:\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+               _("Suggested configuration changes:\n"));
     GNUNET_CONFIGURATION_iterate_section_values (diff,
                                                 "nat",
                                                 &auto_conf_iter,
-                                                NULL);
+                                                new_cfg);
+  }
+
+  /* If desired, write configuration to file; we write only the
+     changes to the defaults to keep things compact. */
+  if ( (write_cfg) &&
+       (NULL != diff) )
+  {
+    struct GNUNET_CONFIGURATION_Handle *def_cfg;
+
+    GNUNET_CONFIGURATION_set_value_string (new_cfg,
+                                          "ARM",
+                                          "CONFIG",
+                                          NULL);
+    def_cfg = GNUNET_CONFIGURATION_create ();
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (def_cfg,
+                                            NULL));
+    if (GNUNET_OK !=
+       GNUNET_CONFIGURATION_write_diffs (def_cfg,
+                                         new_cfg,
+                                         cfg_file))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                 _("Failed to write configuration to `%s'\n"),
+                 cfg_file);
+      global_ret = 1;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                 _("Wrote updated configuration to `%s'\n"),
+                 cfg_file);
+    }
+    GNUNET_CONFIGURATION_destroy (def_cfg);
   }
-  // FIXME: have option to save config
+
+  if (NULL != new_cfg)
+    GNUNET_CONFIGURATION_destroy (new_cfg);
   test_finished ();
 }
 
@@ -387,6 +461,9 @@ run (void *cls,
   struct sockaddr *remote_sa;
   size_t local_len;
   size_t remote_len;
+
+  cfg_file = cfgfile;
+  cfg = c;
   
   if (use_tcp && use_udp)
   {
@@ -631,6 +708,9 @@ main (int argc,
     {'u', "udp", NULL,
      gettext_noop ("use UDP"),
      GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
+    {'w', "write", NULL,
+     gettext_noop ("write configuration file (for autoconfiguration)"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
    GNUNET_GETOPT_OPTION_END
   };
 
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 215c421..af40174 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -28,8 +28,9 @@
  * knowledge about the local network topology.
  *
  * TODO:
- * - implement UPnPC/PMP-based NAT traversal
- * - implement autoconfig
+ * - TEST UPnPC/PMP-based NAT traversal
+ * - implement STUN processing to classify NAT
+ * - implement "more" autoconfig
  * - implement NEW logic for external IP detection
  */
 #include "platform.h"
@@ -77,6 +78,26 @@
 
 
 /**
+ * Information we track per client address. 
+ */
+struct ClientAddress
+{
+  /**
+   * Network address used by the client.
+   */
+  struct sockaddr_storage ss;
+
+  /**
+   * Handle to active UPnP request where we asked upnpc to open
+   * a port at the NAT.  NULL if we do not have such a request
+   * pending.
+   */
+  struct GNUNET_NAT_MiniHandle *mh;
+  
+};
+
+
+/**
  * Internal data structure we track for each of our clients.
  */
 struct ClientHandle
@@ -105,7 +126,7 @@ struct ClientHandle
   /**
    * Array of addresses used by the service.
    */
-  struct sockaddr **addrs;
+  struct ClientAddress *caddrs;
   
   /**
    * What does this client care about?
@@ -113,7 +134,7 @@ struct ClientHandle
   enum GNUNET_NAT_RegisterFlags flags;
 
   /**
-   * Is any of the @e addrs in a reserved subnet for NAT?
+   * Is any of the @e caddrs in a reserved subnet for NAT?
    */
   int natted_address;
   
@@ -125,8 +146,9 @@ struct ClientHandle
 
   /**
    * Number of addresses that this service is bound to.
+   * Length of the @e caddrs array.
    */
-  uint16_t num_addrs;
+  uint16_t num_caddrs;
   
   /**
    * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
@@ -357,6 +379,7 @@ static struct GNUNET_NAT_ExternalHandle 
*probe_external_ip_op;
  */
 static struct in_addr mini_external_ipv4;
 
+
 /**
  * Free the DLL starting at #lal_head.
  */ 
@@ -693,13 +716,13 @@ check_notify_client (struct LocalAddressList *delta,
     GNUNET_memcpy (&v4,
                   &delta->addr,
                   alen);
-    for (unsigned int i=0;i<ch->num_addrs;i++)
+    for (unsigned int i=0;i<ch->num_caddrs;i++)
     {
       const struct sockaddr_in *c4;
       
-      if (AF_INET != ch->addrs[i]->sa_family)
+      if (AF_INET != ch->caddrs[i].ss.ss_family)
        return; /* IPv4 not relevant */
-      c4 = (const struct sockaddr_in *) ch->addrs[i];
+      c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
       v4.sin_port = c4->sin_port;
       notify_client (delta->ac,
                     ch,
@@ -713,13 +736,13 @@ check_notify_client (struct LocalAddressList *delta,
     GNUNET_memcpy (&v6,
                   &delta->addr,
                   alen);
-    for (unsigned int i=0;i<ch->num_addrs;i++)
+    for (unsigned int i=0;i<ch->num_caddrs;i++)
     {
       const struct sockaddr_in6 *c6;
       
-      if (AF_INET6 != ch->addrs[i]->sa_family)
+      if (AF_INET6 != ch->caddrs[i].ss.ss_family)
        return; /* IPv4 not relevant */
-      c6 = (const struct sockaddr_in6 *) ch->addrs[i];
+      c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
       v6.sin6_port = c6->sin6_port;
       notify_client (delta->ac,
                     ch,
@@ -778,13 +801,13 @@ check_notify_client_external_ipv4_change (const struct 
in_addr *v4,
   if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags))
     return;
   bport = 0;
-  for (unsigned int i=0;i<ch->num_addrs;i++)
+  for (unsigned int i=0;i<ch->num_caddrs;i++)
   {
-    const struct sockaddr *sa = ch->addrs[i];
+    const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
 
-    if (AF_INET != sa->sa_family)
+    if (AF_INET != ss->ss_family)
       continue;
-    bport = ntohs (((const struct sockaddr_in *) sa)->sin_port);
+    bport = ntohs (((const struct sockaddr_in *) ss)->sin_port);
   }
   if (0 == bport)
     return; /* IPv6-only */
@@ -1008,6 +1031,66 @@ run_scan (void *cls)
 
 
 /**
+ * Function called whenever our set of external addresses
+ * as created by `upnpc` changes.
+ *
+ * @param cls closure with our `struct ClientHandle *`
+ * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO 
to mean
+ *     the previous (now invalid) one, #GNUNET_SYSERR indicates an error
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific 
error code
+ */
+static void
+upnp_addr_change_cb (void *cls,
+                    int add_remove,
+                    const struct sockaddr *addr,
+                    socklen_t addrlen,
+                    enum GNUNET_NAT_StatusCode result)
+{
+  struct ClientHandle *ch = cls;
+  enum GNUNET_NAT_AddressClass ac;
+
+  switch (result)
+  {
+  case GNUNET_NAT_ERROR_SUCCESS:
+    GNUNET_assert (NULL != addr);
+    break;
+  case GNUNET_NAT_ERROR_UPNPC_FAILED:
+  case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Running upnpc failed: %d\n",
+               result);
+    return;
+  default:
+    GNUNET_break (0); /* should not be possible */
+    return;
+  }
+  switch (addr->sa_family)
+  {
+  case AF_INET:
+    ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
+      ? GNUNET_NAT_AC_LAN_PRIVATE
+      : GNUNET_NAT_AC_GLOBAL_EXTERN;
+    break;
+  case AF_INET6:
+    ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
+      ? GNUNET_NAT_AC_LAN_PRIVATE
+      : GNUNET_NAT_AC_GLOBAL_EXTERN;
+    break;
+  default:
+    GNUNET_break (0);
+    return;
+  }
+  notify_client (ac,
+                ch,
+                add_remove,
+                addr,
+                addrlen);
+}
+
+
+/**
  * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
  * We remember the client for updates upon future NAT events.
  *
@@ -1023,7 +1106,7 @@ handle_register (void *cls,
   size_t left;
 
   if ( (0 != ch->proto) ||
-       (NULL != ch->addrs) )
+       (NULL != ch->caddrs) )
   {
     /* double registration not allowed */
     GNUNET_break (0);
@@ -1035,15 +1118,17 @@ handle_register (void *cls,
   ch->flags = message->flags;
   ch->proto = message->proto;
   ch->adv_port = ntohs (message->adv_port);
-  ch->num_addrs = ntohs (message->num_addrs);
-  ch->addrs = GNUNET_new_array (ch->num_addrs,
-                               struct sockaddr *);
+  ch->num_caddrs = ntohs (message->num_addrs);
+  ch->caddrs = GNUNET_new_array (ch->num_caddrs,
+                                struct ClientAddress);
   left = ntohs (message->header.size) - sizeof (*message);
   off = (const char *) &message[1];
-  for (unsigned int i=0;i<ch->num_addrs;i++)
+  for (unsigned int i=0;i<ch->num_caddrs;i++)
   {
     size_t alen;
     const struct sockaddr *sa = (const struct sockaddr *) off;
+    uint16_t port;
+    int is_nat;
 
     if (sizeof (sa_family_t) > left)
     {
@@ -1051,6 +1136,7 @@ handle_register (void *cls,
       GNUNET_SERVICE_client_drop (ch->client);
       return;
     }
+    is_nat = GNUNET_NO;
     switch (sa->sa_family)
     {
     case AF_INET:
@@ -1059,7 +1145,8 @@ handle_register (void *cls,
        
        alen = sizeof (struct sockaddr_in);
        if (is_nat_v4 (&s4->sin_addr))
-         ch->natted_address = GNUNET_YES;
+         is_nat = GNUNET_YES;
+       port = ntohs (s4->sin_port);
       }
       break;
     case AF_INET6:
@@ -1068,12 +1155,14 @@ handle_register (void *cls,
        
        alen = sizeof (struct sockaddr_in6);
        if (is_nat_v6 (&s6->sin6_addr))
-         ch->natted_address = GNUNET_YES;
+         is_nat = GNUNET_YES;
+       port = ntohs (s6->sin6_port);
       }
       break;
 #if AF_UNIX
     case AF_UNIX:
       alen = sizeof (struct sockaddr_un);
+      port = 0;
       break;
 #endif
     default:
@@ -1081,11 +1170,27 @@ handle_register (void *cls,
       GNUNET_SERVICE_client_drop (ch->client);
       return;      
     }
+    /* store address */
     GNUNET_assert (alen <= left);
-    ch->addrs[i] = GNUNET_malloc (alen);
-    GNUNET_memcpy (ch->addrs[i],
+    GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
+    GNUNET_memcpy (&ch->caddrs[i].ss,
                   sa,
                   alen);    
+
+    /* If applicable, try UPNPC NAT punching */
+    if ( (is_nat) &&
+        (enable_upnp) &&
+        ( (IPPROTO_TCP == ch->proto) ||
+          (IPPROTO_UDP == ch->proto) ) )
+    {
+      ch->natted_address = GNUNET_YES;
+      ch->caddrs[i].mh
+       = GNUNET_NAT_mini_map_start (port,
+                                    IPPROTO_TCP == ch->proto,
+                                    &upnp_addr_change_cb,
+                                    ch);
+    }
+
     off += alen;
   }
   /* Actually send IP address list to client */
@@ -1822,9 +1927,15 @@ client_disconnect_cb (void *cls,
   GNUNET_CONTAINER_DLL_remove (ch_head,
                               ch_tail,
                               ch);
-  for (unsigned int i=0;i<ch->num_addrs;i++)
-    GNUNET_free_non_null (ch->addrs[i]);
-  GNUNET_free_non_null (ch->addrs);
+  for (unsigned int i=0;i<ch->num_caddrs;i++)
+  {
+    if (NULL != ch->caddrs[i].mh)
+    {
+      GNUNET_NAT_mini_map_stop (ch->caddrs[i].mh);
+      ch->caddrs[i].mh = NULL;
+    }
+  }
+  GNUNET_free_non_null (ch->caddrs);
   GNUNET_free (ch);
 }
 
diff --git a/src/nat/gnunet-service-nat_mini.c 
b/src/nat/gnunet-service-nat_mini.c
index 658ec72..efdc098 100644
--- a/src/nat/gnunet-service-nat_mini.c
+++ b/src/nat/gnunet-service-nat_mini.c
@@ -431,7 +431,7 @@ process_refresh_output (void *cls,
     }
     return;
   }
-  if (!mini->did_map)
+  if (! mini->did_map)
     return;                     /* never mapped, won't find our mapping anyway 
*/
 
   /* we're looking for output of the form:
@@ -538,8 +538,8 @@ do_refresh (void *cls)
     mini->refresh_cmd = NULL;
     ac = GNUNET_YES;
   }
-  mini->refresh_cmd =
-      GNUNET_OS_command_run (&process_refresh_output,
+  mini->refresh_cmd 
+    = GNUNET_OS_command_run (&process_refresh_output,
                             mini,
                             MAP_TIMEOUT,
                              "upnpc",
@@ -581,10 +581,10 @@ process_map_output (void *cls,
                 NULL, 0,
                 GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED);
     if (NULL == mini->refresh_task)
-      mini->refresh_task =
-        GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
-                                     &do_refresh,
-                                     mini);
+      mini->refresh_task 
+        = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
+                                       &do_refresh,
+                                       mini);
     return;
   }
   /*
@@ -600,7 +600,9 @@ process_map_output (void *cls,
   }
   ipa = GNUNET_strdup (ipaddr + 1);
   strstr (ipa, ":")[0] = '\0';
-  if (1 != inet_pton (AF_INET, ipa, &mini->current_addr.sin_addr))
+  if (1 != inet_pton (AF_INET,
+                     ipa,
+                     &mini->current_addr.sin_addr))
   {
     GNUNET_free (ipa);
     return;                     /* skip line */
@@ -613,7 +615,8 @@ process_map_output (void *cls,
   mini->current_addr.sin_len = sizeof (struct sockaddr_in);
 #endif
   mini->did_map = GNUNET_YES;
-  mini->ac (mini->ac_cls, GNUNET_YES,
+  mini->ac (mini->ac_cls,
+           GNUNET_YES,
             (const struct sockaddr *) &mini->current_addr,
             sizeof (mini->current_addr),
             GNUNET_NAT_ERROR_SUCCESS);

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



reply via email to

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