gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] branch master updated (56b93c5ca -> 2652a92f5)


From: gnunet
Subject: [gnunet] branch master updated (56b93c5ca -> 2652a92f5)
Date: Fri, 27 Jan 2023 13:17:07 +0100

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

t3sserakt pushed a change to branch master
in repository gnunet.

    from 56b93c5ca gana: update for format.sh fix
     new 6de2cb8f7 TNG: - Added topology file for tcp icmp nat hole punching 
test case.      - Added code to configure connection attempts to natted peers.
     new a21cb1820 TNG: Added code in the netjail scripts to enable router 
nodes to forward icmp requests and response.
     new 1a95d92b4 TNG: Added nat reversal code to tcp communicator. Prepared 
udp communicator.
     new f5d40212b TNG: Fixed bug happening during check for pending validation 
requests after nat reversal.
     new d3d994d33 TNG: Added tcp icmp nat hole punching test case script, and 
fixed bugs occuring during shutdown.
     new 2652a92f5 Merge branch 'master' of ssh://git.gnunet.org/gnunet

The 6 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:
 contrib/netjail/netjail_core.sh                    |  14 +-
 contrib/netjail/netjail_start.sh                   |  34 +-
 src/testing/testing.c                              |  22 +-
 .../testing_api_cmd_netjail_start_cmds_helper.c    |   4 +-
 src/transport/Makefile.am                          |   2 +
 src/transport/gnunet-communicator-tcp.c            | 729 ++++++++++++++++-----
 src/transport/gnunet-communicator-udp.c            |   9 +-
 src/transport/gnunet-service-tng.c                 |  53 +-
 .../test_transport_nat_icmp_tcp_topo.conf          |   7 +
 src/transport/transport_api2_communication.c       |  21 +-
 src/transport/transport_api_cmd_connecting_peers.c |  27 +-
 src/transport/transport_api_cmd_start_peer.c       |   6 +-
 src/util/mq.c                                      |   4 -
 13 files changed, 707 insertions(+), 225 deletions(-)
 create mode 100644 src/transport/test_transport_nat_icmp_tcp_topo.conf

diff --git a/contrib/netjail/netjail_core.sh b/contrib/netjail/netjail_core.sh
index 302ae922f..cb2a271b8 100755
--- a/contrib/netjail/netjail_core.sh
+++ b/contrib/netjail/netjail_core.sh
@@ -145,12 +145,12 @@ netjail_node_link_bridge() {
        local BRIDGE=$2
        local ADDRESS=$3
        local MASK=$4
-       
+
        netjail_next_interface
        local NUM_IF=$RESULT
        netjail_next_interface
        local NUM_BR=$RESULT
-       
+
        local LINK_IF=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX 
$NUM_IF)
        local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX 
$NUM_BR)
 
@@ -163,18 +163,18 @@ netjail_node_link_bridge() {
        ip -n $NODE link set up dev lo
 
        ip link set $LINK_BR up
-       
-       RESULT=$LINK_BR
+
+       RESULT=$LINK_IF
 }
 
 netjail_node_link_bridge_name() {
-       
+
        netjail_next_interface
        netjail_next_interface
        local NUM_BR=$RESULT
-       
+
        local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX 
$NUM_BR)
-       
+
        RESULT=$LINK_BR
 }
 
diff --git a/contrib/netjail/netjail_start.sh b/contrib/netjail/netjail_start.sh
index e68745746..35e51abb4 100755
--- a/contrib/netjail/netjail_start.sh
+++ b/contrib/netjail/netjail_start.sh
@@ -52,6 +52,13 @@ for X in $(seq $KNOWN); do
        KNOWN_NODES[$X]=$RESULT
        netjail_node_link_bridge ${KNOWN_NODES[$X]} $NETWORK_NET 
"$KNOWN_GROUP.$X" 16
        KNOWN_LINKS[$X]=$RESULT
+
+    # Execute echo 1 > /proc/sys/net/netfilter/nf_log_all_netns to make 
itables log to the host.
+    #ip netns exec ${KNOWN_NODES[$X]} iptables -A INPUT -j LOG --log-prefix 
'** Known ${KNOWN_NODES[$X]}  **'
+    #ip netns exec ${KNOWN_NODES[$X]} iptables -A OUTPUT -j LOG --log-prefix 
'** Known ${KNOWN_NODES[$X]}  **'
+    ip netns exec ${KNOWN_NODES[$X]} iptables -A OUTPUT -p icmp -j ACCEPT
+    ip netns exec ${KNOWN_NODES[$X]} iptables -A INPUT -p icmp -j ACCEPT
+    
 done
 
 declare -A NODES
@@ -61,18 +68,36 @@ for N in $(seq $GLOBAL_N); do
        netjail_node
        ROUTERS[$N]=$RESULT
        netjail_node_link_bridge ${ROUTERS[$N]} $NETWORK_NET "$GLOBAL_GROUP.$N" 
16
-       NETWORK_LINKS[$N]=$RESULT
+       ROUTER_EXT_IF[$N]=$RESULT
        netjail_bridge
        ROUTER_NETS[$N]=$RESULT
-       
+
+    #ip netns exec ${ROUTERS[$N]} iptables -A INPUT -j LOG --log-prefix '** 
Router ${ROUTERS[$N]}  **'
+    ip netns exec ${ROUTERS[$N]} iptables -A INPUT -p icmp -j ACCEPT
+    ip netns exec ${ROUTERS[$N]} iptables -t nat -A PREROUTING -p icmp -d 
$GLOBAL_GROUP.$N -j DNAT --to $LOCAL_GROUP.1
+    ip netns exec ${ROUTERS[$N]} iptables -A FORWARD -p icmp -d $LOCAL_GROUP.1 
 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
+    #ip netns exec ${ROUTERS[$N]} iptables -A OUTPUT -j LOG --log-prefix '** 
Router ${ROUTERS[$N]}  **'
+    ip netns exec ${ROUTERS[$N]} iptables -A OUTPUT -p icmp -j ACCEPT
+    
        for M in $(seq $LOCAL_M); do
                netjail_node
                NODES[$N,$M]=$RESULT
                netjail_node_link_bridge ${NODES[$N,$M]} ${ROUTER_NETS[$N]} 
"$LOCAL_GROUP.$M" 24
                NODE_LINKS[$N,$M]=$RESULT
+
+        #ip netns exec ${NODES[$N,$M]} iptables -A INPUT -j LOG --log-prefix 
'** Node ${NODES[$N,$M]}  **'
+        #ip netns exec ${NODES[$N,$M]} iptables -A OUTPUT -j LOG --log-prefix 
'** Node ${NODES[$N,$M]}  **'
+        ip netns exec ${NODES[$N,$M]} iptables -A OUTPUT -p icmp -j ACCEPT
+        ip netns exec ${NODES[$N,$M]} iptables -A INPUT -p icmp -j ACCEPT 
        done
 
        ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))"
+
+    let X=$KNOWN+1
+    ip netns exec ${ROUTERS[$N]} ip route add "$KNOWN_GROUP.$X" dev 
${ROUTER_EXT_IF[$N]}
+    ip netns exec ${ROUTERS[$N]} ip route add default via "$KNOWN_GROUP.$X"
+
+    
        netjail_node_link_bridge ${ROUTERS[$N]} ${ROUTER_NETS[$N]} $ROUTER_ADDR 
24
        ROUTER_LINKS[$N]=$RESULT
        
@@ -135,3 +160,8 @@ for N in $(seq $GLOBAL_N); do
         ip netns exec ${ROUTERS[$N]} ./${R_SCRIPT[$N]} ${ROUTER_NETS[$N]} 1
     fi
 done
+
+# We like to have a node acting as a gateway for all router nodes. This is 
especially needed for sending fake ICMP packets.
+netjail_node
+GATEWAY=$RESULT
+netjail_node_link_bridge $GATEWAY $NETWORK_NET "$KNOWN_GROUP.$X" 16
diff --git a/src/testing/testing.c b/src/testing/testing.c
index a1161925b..2a9b0309f 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -63,6 +63,10 @@
 
 #define PREFIX_UDP "udp"
 
+#define PREFIX_TCP_NATTED "tcp_natted"
+
+#define PREFIX_UDP_NATTED "udp_natted"
+
 /**
  * Lowest port used for GNUnet testing.  Should be high enough to not
  * conflict with other applications running on the hosts but be low
@@ -1914,7 +1918,7 @@ get_value (const char *key, const char *line)
  * Every line in the topology configuration starts with a string indicating 
which 
  * kind of information will be configured with this line. Configuration values 
following
  * this string are seperated by special sequences of characters. A value might 
be 
- * a key value pair. A special key is the 'connect' which can appear more than 
once.
+ * a key value pair. A special key is the 'connect' key which can appear more 
than once.
  * The value is the information about a connection via some protocol to some 
other node.
  * This function returns the struct GNUNET_TESTING_NodeConnection which holds 
the information
  * of the connect value.
@@ -2419,7 +2423,8 @@ GNUNET_TESTING_get_address (struct 
GNUNET_TESTING_NodeConnection *connection,
   unsigned int node_n;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "node_n: %u\n",
+       "get address prefix: %s node_n: %u\n",
+       prefix,
        connection->node_n);
 
   node = connection->node;
@@ -2443,15 +2448,10 @@ GNUNET_TESTING_get_address (struct 
GNUNET_TESTING_NodeConnection *connection,
     return NULL;
   }
 
-  if (0 == strcmp (PREFIX_TCP, prefix))
-  {
-
-    GNUNET_asprintf (&addr,
-                     template,
-                     prefix,
-                     node_n);
-  }
-  else if (0 == strcmp (PREFIX_UDP, prefix))
+  if (0 == strcmp (PREFIX_TCP, prefix) ||
+      0 == strcmp (PREFIX_UDP, prefix) ||
+      0 == strcmp (PREFIX_UDP_NATTED, prefix) ||
+      0 == strcmp (PREFIX_TCP_NATTED, prefix))
   {
     GNUNET_asprintf (&addr,
                      template,
diff --git a/src/testing/testing_api_cmd_netjail_start_cmds_helper.c 
b/src/testing/testing_api_cmd_netjail_start_cmds_helper.c
index 545b89b33..619392119 100644
--- a/src/testing/testing_api_cmd_netjail_start_cmds_helper.c
+++ b/src/testing/testing_api_cmd_netjail_start_cmds_helper.c
@@ -489,6 +489,7 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader 
*message)
     } else if (ns->number_of_local_tests_finished == total_number)
     {
       GNUNET_SCHEDULER_cancel (ns->timeout_task);
+      ns->timeout_task = NULL;
       GNUNET_TESTING_async_finish (&ns->ac);
     }
     break;
@@ -525,7 +526,8 @@ exp_cb (void *cls)
   struct NetJailState *ns = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
-  GNUNET_SCHEDULER_cancel (ns->timeout_task);
+  if (NULL != ns->timeout_task)
+    GNUNET_SCHEDULER_cancel (ns->timeout_task);
   GNUNET_TESTING_async_fail (&(ns->ac));
 }
 
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 0059861c2..5acba3a4e 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -760,6 +760,7 @@ endif
 # Only test TNG if we run experimental
 if HAVE_EXPERIMENTAL
 check_SCRIPTS= \
+test_transport_nat_icmp_tcp.sh \
   test_transport_nat_upnp.sh \
   test_transport_simple_send_string.sh \
   test_transport_simple_send.sh \
@@ -1509,6 +1510,7 @@ test_transport_api_slow_ats_LDADD = \
 
 
 EXTRA_DIST = \
+test_transport_nat_icmp_tcp.sh \
 test_transport_nat_upnp.sh \
 test_transport_simple_send_string.sh \
 test_transport_simple_send.sh \
diff --git a/src/transport/gnunet-communicator-tcp.c 
b/src/transport/gnunet-communicator-tcp.c
index 84aa45b9a..86b98cee1 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -40,6 +40,13 @@
 #include "gnunet_transport_communication_service.h"
 #include "gnunet_resolver_service.h"
 
+
+/**
+ * How long until we give up on establishing an NAT connection?
+ * Must be > 4 RTT
+ */
+#define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
10)
+
 /**
  * How long do we believe our addresses to remain up (before
  * the other peer should revalidate).
@@ -364,9 +371,46 @@ struct TCPFinish
   struct GNUNET_ShortHashCode hmac;
 };
 
+/**
+ * Basically a WELCOME message, but with the purpose
+ * of giving the waiting peer a client handle to use
+ */
+struct TCPNATProbeMessage
+{
+  /**
+   * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Identity of the sender of the message.
+   */
+  struct GNUNET_PeerIdentity clientIdentity;
+};
 
 GNUNET_NETWORK_STRUCT_END
 
+/**
+ * Struct for pending nat reversals.
+ */
+struct PendingReversal
+{
+  /*
+   * Timeout task.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * To whom are we like to talk to.
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Address the reversal was send to.
+   */
+  struct sockaddr *in;
+};
+
 /**
  * Struct to use as closure.
  */
@@ -652,6 +696,21 @@ struct ProtoQueue
    */
   struct GNUNET_NETWORK_Handle *sock;
 
+  /**
+   * ID of write task for this connection.
+   */
+  struct GNUNET_SCHEDULER_Task *write_task;
+
+  /**
+   * buffer for writing struct TCPNATProbeMessage to network.
+   */
+  char write_buf[sizeof (struct TCPNATProbeMessage)];
+
+  /**
+   * Offset of the buffer?
+   */
+  size_t write_off;
+
   /**
    * ID of read task for this connection.
    */
@@ -855,6 +914,11 @@ int shutdown_running = GNUNET_NO;
  */
 unsigned int bind_port;
 
+/**
+ *  Map of pending reversals.
+ */
+struct GNUNET_CONTAINER_MultiHashMap *pending_reversals;
+
 /**
  * We have been notified that our listen socket has something to
  * read. Do the read and reschedule this function to be called again
@@ -1568,6 +1632,134 @@ inject_rekey (struct Queue *queue)
   setup_out_cipher (queue);
 }
 
+static int
+pending_reversals_delete_it (void *cls,
+                  const struct GNUNET_HashCode *key,
+                  void *value)
+{
+  (void) cls;
+  struct PendingReversal *pending_reversal = value;
+
+  if (NULL != pending_reversal->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
+    pending_reversal->timeout_task = NULL;
+  }
+  GNUNET_CONTAINER_multihashmap_remove (pending_reversals,
+                                        key,
+                                        pending_reversal);
+  GNUNET_free (pending_reversal->in);
+  GNUNET_free (pending_reversal);
+  return GNUNET_OK;
+}
+
+
+static void
+check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family, 
struct GNUNET_PeerIdentity *sender)
+{
+  if (AF_INET == sa_family)
+      {
+        struct PendingReversal *pending_reversal;
+        struct GNUNET_HashCode key;
+        struct sockaddr_in *natted_address;
+
+        natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
+        natted_address->sin_port = 0;
+        GNUNET_CRYPTO_hash (natted_address,
+                            sizeof(struct sockaddr),
+                            &key);
+
+        pending_reversal = GNUNET_CONTAINER_multihashmap_get 
(pending_reversals,
+                                                              &key);
+        if (NULL != pending_reversal && (NULL == sender ||
+                                         0 != memcmp (sender, 
&pending_reversal->target, sizeof(struct GNUNET_PeerIdentity))))
+        {
+            GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                        "Removing invalid pending reversal for `%s'at `%s'\n",
+                        GNUNET_i2s (&pending_reversal->target),
+                        GNUNET_a2s (in, sizeof (in)));
+                        pending_reversals_delete_it (NULL, &key, 
pending_reversal);
+        }
+        GNUNET_free (natted_address);
+      }
+}
+
+
+/**
+ * Closes socket and frees memory associated with @a pq.
+ *
+ * @param pq proto queue to free
+ */
+static void
+free_proto_queue (struct ProtoQueue *pq)
+{
+  if (NULL != pq->listen_sock)
+  {
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock));
+    pq->listen_sock = NULL;
+  }
+  if (NULL != pq->read_task)
+  {
+    GNUNET_SCHEDULER_cancel (pq->read_task);
+    pq->read_task = NULL;
+  }
+  if (NULL != pq->write_task)
+  {
+    GNUNET_SCHEDULER_cancel (pq->write_task);
+    pq->write_task = NULL;
+  }
+  check_and_remove_pending_reversal (pq->address, pq->address->sa_family, 
NULL);
+  GNUNET_NETWORK_socket_close (pq->sock);
+  GNUNET_free (pq->address);
+  GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
+  GNUNET_free (pq);
+}
+
+
+/**
+ * We have been notified that our socket is ready to write.
+ * Then reschedule this function to be called again once more is available.
+ *
+ * @param cls a `struct ProtoQueue`
+ */
+static void
+proto_queue_write (void *cls)
+{
+  struct ProtoQueue *pq = cls;
+  ssize_t sent;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
+  pq->write_task = NULL;
+  if (0 != pq->write_off)
+  {
+    sent = GNUNET_NETWORK_socket_send (pq->sock,
+                                       pq->write_buf,
+                                       pq->write_off);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sent %lu bytes to TCP queue\n", sent);
+    if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
+      free_proto_queue (pq);
+      return;
+    }
+    if (sent > 0)
+    {
+      size_t usent = (size_t) sent;
+      pq->write_off -= usent;
+      memmove (pq->write_buf,
+               &pq->write_buf[usent],
+               pq->write_off);
+    }
+  }
+  /* do we care to write more? */
+  if ((0 < pq->write_off))
+    pq->write_task =
+      GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pq->sock,
+                                      &proto_queue_write,
+                                      pq);
+}
+
 
 /**
  * We have been notified that our socket is ready to write.
@@ -1779,6 +1971,10 @@ try_handle_plaintext (struct Queue *queue)
                                         &queue_write,
                                         queue);
     }
+    else if (GNUNET_TRANSPORT_CS_OUTBOUND ==     queue->cs)
+    {
+      check_and_remove_pending_reversal (queue->address, 
queue->address->sa_family, NULL);
+    }
 
     unverified_size = -1;
 
@@ -2659,22 +2855,99 @@ decrypt_and_check_tc (struct Queue *queue,
 
 
 /**
- * Closes socket and frees memory associated with @a pq.
+ * Read from the socket of the queue until we have enough data
+ * to initialize the decryption logic and can switch to regular
+ * reading.
  *
- * @param pq proto queue to free
+ * @param cls a `struct Queue`
  */
 static void
-free_proto_queue (struct ProtoQueue *pq)
+queue_read_kx (void *cls)
 {
-  if (NULL != pq->listen_sock)
+  struct Queue *queue = cls;
+  ssize_t rcvd;
+  struct GNUNET_TIME_Relative left;
+  struct TCPConfirmation tc;
+
+  queue->read_task = NULL;
+  left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
+  if (0 == left.rel_value_us)
   {
-    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock));
-    pq->listen_sock = NULL;
+    queue_destroy (queue);
+    return;
   }
-  GNUNET_NETWORK_socket_close (pq->sock);
-  GNUNET_free (pq->address);
-  GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
-  GNUNET_free (pq);
+  rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
+                                     &queue->cread_buf[queue->cread_off],
+                                     BUF_SIZE - queue->cread_off);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received %lu bytes for KX\n",
+              rcvd);
+  GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
+                           "transport",
+                           "Received %lu bytes for KX\n",
+                           rcvd);
+  if (-1 == rcvd)
+  {
+    if ((EAGAIN != errno) && (EINTR != errno))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
+      queue_destroy (queue);
+      return;
+    }
+    queue->read_task =
+      GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
+    return;
+  }
+  queue->cread_off += rcvd;
+  if (queue->cread_off < INITIAL_KX_SIZE)
+  {
+    /* read more */
+    queue->read_task =
+      GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
+    return;
+  }
+  /* we got all the data, let's find out who we are talking to! */
+  setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *)
+                   queue->cread_buf,
+                   queue);
+  if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Invalid TCP KX received from %s\n",
+                GNUNET_a2s (queue->address, queue->address_len));
+    queue_destroy (queue);
+    return;
+  }
+  if (0 !=
+      memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid sender in TCP KX received from %s\n",
+                GNUNET_a2s (queue->address, queue->address_len));
+    queue_destroy (queue);
+    return;
+  }
+  send_challenge (tc.challenge, queue);
+  queue->write_task =
+    GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                    queue->sock,
+                                    &queue_write,
+                                    queue);
+
+  /* update queue timeout */
+  reschedule_queue_timeout (queue);
+  /* prepare to continue with regular read task immediately */
+  memmove (queue->cread_buf,
+           &queue->cread_buf[INITIAL_KX_SIZE],
+           queue->cread_off - (INITIAL_KX_SIZE));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "cread_off is %lu bytes before adjusting\n",
+              queue->cread_off);
+  queue->cread_off -= INITIAL_KX_SIZE;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "cread_off set to %lu bytes\n",
+              queue->cread_off);
+  queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
 }
 
 
@@ -2692,6 +2965,7 @@ proto_read_kx (void *cls)
   struct GNUNET_TIME_Relative left;
   struct Queue *queue;
   struct TCPConfirmation tc;
+  GNUNET_SCHEDULER_TaskCallback read_task;
 
   pq->read_task = NULL;
   left = GNUNET_TIME_absolute_get_remaining (pq->timeout);
@@ -2704,10 +2978,10 @@ proto_read_kx (void *cls)
                                      &pq->ibuf[pq->ibuf_off],
                                      sizeof(pq->ibuf) - pq->ibuf_off);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received %lu bytes for KX\n", rcvd);
+              "Proto received %lu bytes for KX\n", rcvd);
   GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
                            "transport",
-                           "Received %lu bytes for KX\n", rcvd);
+                           "Proto received %lu bytes for KX\n", rcvd);
   if (-1 == rcvd)
   {
     if ((EAGAIN != errno) && (EINTR != errno))
@@ -2722,30 +2996,46 @@ proto_read_kx (void *cls)
     return;
   }
   pq->ibuf_off += rcvd;
-  if (pq->ibuf_off > sizeof(pq->ibuf))
+  if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
+  {
+    struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
+
+    check_and_remove_pending_reversal (pq->address, pq->address->sa_family, 
&pm->clientIdentity);
+
+    queue = GNUNET_new (struct Queue);
+    queue->target = pm->clientIdentity;
+    queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
+    read_task = &queue_read_kx;
+  }
+  else if (pq->ibuf_off > sizeof(pq->ibuf))
   {
     /* read more */
     pq->read_task =
       GNUNET_SCHEDULER_add_read_net (left, pq->sock, &proto_read_kx, pq);
     return;
   }
-  /* we got all the data, let's find out who we are talking to! */
-  queue = GNUNET_new (struct Queue);
-  setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
-                   queue);
-  if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Invalid TCP KX received from %s\n",
-                GNUNET_a2s (pq->address, pq->address_len));
-    gcry_cipher_close (queue->in_cipher);
-    GNUNET_free (queue);
-    free_proto_queue (pq);
-    return;
+    /* we got all the data, let's find out who we are talking to! */
+    queue = GNUNET_new (struct Queue);
+    setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
+                     queue);
+    if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Invalid TCP KX received from %s\n",
+                    GNUNET_a2s (pq->address, pq->address_len));
+        gcry_cipher_close (queue->in_cipher);
+        GNUNET_free (queue);
+        free_proto_queue (pq);
+        return;
+    }
+    queue->target = tc.sender;
+    queue->cs = GNUNET_TRANSPORT_CS_INBOUND;
+    read_task = &queue_read;
   }
   queue->address = pq->address; /* steals reference */
   queue->address_len = pq->address_len;
-  queue->target = tc.sender;
   queue->listen_sock = pq->listen_sock;
   queue->sock = pq->sock;
 
@@ -2757,12 +3047,11 @@ proto_read_kx (void *cls)
               "start kx proto\n");
 
   start_initial_kx_out (queue);
-  queue->cs = GNUNET_TRANSPORT_CS_INBOUND;
   boot_queue (queue);
   queue->read_task =
     GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
                                    queue->sock,
-                                   &queue_read,
+                                   read_task,
                                    queue);
   queue->write_task =
     GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
@@ -2777,6 +3066,51 @@ proto_read_kx (void *cls)
   GNUNET_free (pq);
 }
 
+static struct ProtoQueue *
+create_proto_queue (struct GNUNET_NETWORK_Handle *sock,
+                    struct sockaddr *in,
+                    socklen_t addrlen)
+{
+  struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
+
+  if (NULL == sock)
+  {
+    //sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
+    sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
+    if (NULL == sock)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "socket(%d) failed: %s",
+                    in->sa_family,
+                    strerror (errno));
+        GNUNET_free (in);
+        return NULL;
+      }
+    if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
+        (errno != EINPROGRESS))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "connect to `%s' failed: %s",
+                    GNUNET_a2s (in, addrlen),
+                    strerror (errno));
+        GNUNET_NETWORK_socket_close (sock);
+        GNUNET_free (in);
+        return NULL;
+      }
+  }
+  pq->address_len = addrlen;
+  pq->address = in;
+  pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
+  pq->sock = sock;
+  pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
+                                                 pq->sock,
+                                                 &proto_read_kx,
+                                                 pq);
+  GNUNET_CONTAINER_DLL_insert (proto_head, proto_tail, pq);
+
+  return pq;
+}
+
 
 /**
  * We have been notified that our listen socket has something to
@@ -2793,6 +3127,7 @@ listen_cb (void *cls)
   struct GNUNET_NETWORK_Handle *sock;
   struct ProtoQueue *pq;
   struct ListenTask *lt;
+  struct sockaddr *in_addr;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "listen_cb\n");
@@ -2819,113 +3154,71 @@ listen_cb (void *cls)
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
     return;
   }
-  pq = GNUNET_new (struct ProtoQueue);
-  pq->address_len = addrlen;
-  pq->address = GNUNET_memdup (&in, addrlen);
-  pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
-  pq->sock = sock;
-  pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
-                                                 pq->sock,
-                                                 &proto_read_kx,
-                                                 pq);
-  GNUNET_CONTAINER_DLL_insert (proto_head, proto_tail, pq);
+  in_addr = GNUNET_memdup (&in, addrlen);
+  create_proto_queue (sock, in_addr, addrlen);
 }
 
 
-/**
- * Read from the socket of the queue until we have enough data
- * to initialize the decryption logic and can switch to regular
- * reading.
- *
- * @param cls a `struct Queue`
- */
 static void
-queue_read_kx (void *cls)
+try_connection_reversal (void *cls,
+                         const struct sockaddr *addr,
+                         socklen_t addrlen)
 {
-  struct Queue *queue = cls;
-  ssize_t rcvd;
-  struct GNUNET_TIME_Relative left;
-  struct TCPConfirmation tc;
+  (void) cls;
+  struct TCPNATProbeMessage pm;
+  struct ProtoQueue *pq;
+  struct sockaddr *in_addr;
 
-  queue->read_task = NULL;
-  left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
-  if (0 == left.rel_value_us)
-  {
-    queue_destroy (queue);
-    return;
-  }
-  rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
-                                     &queue->cread_buf[queue->cread_off],
-                                     BUF_SIZE - queue->cread_off);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received %lu bytes for KX\n",
-              rcvd);
-  GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
-                           "transport",
-                           "Received %lu bytes for KX\n",
-                           rcvd);
-  if (-1 == rcvd)
-  {
-    if ((EAGAIN != errno) && (EINTR != errno))
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
-      queue_destroy (queue);
-      return;
-    }
-    queue->read_task =
-      GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
-    return;
-  }
-  queue->cread_off += rcvd;
-  if (queue->cread_off < INITIAL_KX_SIZE)
-  {
-    /* read more */
-    queue->read_task =
-      GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
-    return;
-  }
-  /* we got all the data, let's find out who we are talking to! */
-  setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *)
-                   queue->cread_buf,
-                   queue);
-  if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Invalid TCP KX received from %s\n",
-                GNUNET_a2s (queue->address, queue->address_len));
-    queue_destroy (queue);
-    return;
+                    "addr->sa_family %d\n",
+                    addr->sa_family);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Try to connect back\n");
+  in_addr = GNUNET_memdup (addr, addrlen);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "in_addr->sa_family %d\n",
+                    in_addr->sa_family);
+  pq = create_proto_queue (NULL, in_addr, addrlen);
+  if (NULL != pq)
+  {
+      pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
+      pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
+      pm.clientIdentity = my_identity;
+      memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
+      pq->write_off = sizeof(struct TCPNATProbeMessage);
+      pq->write_task = GNUNET_SCHEDULER_add_write_net (PROTO_QUEUE_TIMEOUT,
+                                                       pq->sock,
+                                                       &proto_queue_write,
+                                                       pq);
   }
-  if (0 !=
-      memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid sender in TCP KX received from %s\n",
-                GNUNET_a2s (queue->address, queue->address_len));
-    queue_destroy (queue);
-    return;
+     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
   }
-  send_challenge (tc.challenge, queue);
-  queue->write_task =
-    GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                    queue->sock,
-                                    &queue_write,
-                                    queue);
+}
 
-  /* update queue timeout */
-  reschedule_queue_timeout (queue);
-  /* prepare to continue with regular read task immediately */
-  memmove (queue->cread_buf,
-           &queue->cread_buf[INITIAL_KX_SIZE],
-           queue->cread_off - (INITIAL_KX_SIZE));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "cread_off is %lu bytes before adjusting\n",
-              queue->cread_off);
-  queue->cread_off -= INITIAL_KX_SIZE;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "cread_off set to %lu bytes\n",
-              queue->cread_off);
-  queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
+
+static void
+pending_reversal_timeout (void *cls)
+{
+  struct sockaddr *in = cls;
+  struct PendingReversal *pending_reversal;
+  struct GNUNET_HashCode key;
+
+  GNUNET_CRYPTO_hash (in,
+                      sizeof(struct sockaddr),
+                      &key);
+  pending_reversal = GNUNET_CONTAINER_multihashmap_get (pending_reversals,
+                                                        &key);
+
+  GNUNET_assert (NULL != pending_reversal);
+
+  GNUNET_CONTAINER_multihashmap_remove (pending_reversals,
+                                        &key,
+                                        pending_reversal);
+  GNUNET_free (pending_reversal->in);
+  GNUNET_free (pending_reversal);
 }
 
 
@@ -2950,17 +3243,18 @@ queue_read_kx (void *cls)
 static int
 mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char 
*address)
 {
-  struct Queue *queue;
-  const char *path;
   struct sockaddr *in;
   socklen_t in_len = 0;
-  struct GNUNET_NETWORK_Handle *sock;
+  const char *path;
+  struct sockaddr_in *v4;
+  struct sockaddr_in6 *v6;
+  unsigned int is_natd = GNUNET_NO;
+  struct GNUNET_HashCode key;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting to %s\n", address);
-  GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
-                           "transport",
-                           "Connecting to %s\n", address);
+              "Connecting to %s at %s\n",
+              GNUNET_i2s (peer),
+              address);
   if (0 != strncmp (address,
                     COMMUNICATOR_ADDRESS_PREFIX "-",
                     strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
@@ -2982,55 +3276,135 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity 
*peer, const char *address)
               "in %s\n",
               GNUNET_a2s (in, in_len));
 
-  sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 
IPPROTO_TCP);
-  if (NULL == sock)
+  switch (in->sa_family)
+    {
+    case AF_INET:
+      v4 = (struct sockaddr_in *) in;
+      if (0 == v4->sin_port){
+        is_natd = GNUNET_YES;
+        GNUNET_CRYPTO_hash (in,
+                      sizeof(struct sockaddr),
+                      &key);
+        if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains 
(pending_reversals,
+                                                                   &key))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "There is already a request reversal for `%s'at `%s'\n",
+                      GNUNET_i2s (peer),
+                      address);
+          GNUNET_free (in);
+          return GNUNET_SYSERR;
+        }
+      }
+      break;
+
+    case AF_INET6:
+      v6 = (struct sockaddr_in6 *) in;
+      if (0 == v6->sin6_port)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Request reversal for `%s' at `%s' not possible for an 
IPv6 address\n",
+                      GNUNET_i2s (peer),
+                      address);
+        GNUNET_free (in);
+        return GNUNET_SYSERR;
+      }
+      break;
+
+    default:
+      GNUNET_assert (0);
+    }
+
+  if (GNUNET_YES == is_natd)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "socket(%d) failed: %s",
-                in->sa_family,
-                strerror (errno));
-    GNUNET_free (in);
-    return GNUNET_SYSERR;
+    struct sockaddr_in local_sa;
+    struct PendingReversal *pending_reversal;
+
+    memset (&local_sa, 0, sizeof(local_sa));
+    local_sa.sin_family = AF_INET;
+    local_sa.sin_port = htons (bind_port);
+    /* We leave sin_address at 0, let the kernel figure it out,
+       even if our bind() is more specific.  (May want to reconsider
+       later.) */
+    if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "request reversal for `%s' at `%s' failed\n",
+                      GNUNET_i2s (peer),
+                      address);
+      GNUNET_free (in);
+      return GNUNET_SYSERR;
+    }
+    pending_reversal = GNUNET_new (struct PendingReversal);
+    pending_reversal->in = in;
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (pending_reversals,
+                                                      &key,
+                                                      pending_reversal,
+                                                      
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    pending_reversal->target = *peer;
+    pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed 
(NAT_TIMEOUT, &pending_reversal_timeout, in);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+         "Created NAT WAIT connection to `%s' at `%s'\n",
+         GNUNET_i2s (peer),
+         GNUNET_a2s (in, sizeof (struct sockaddr)));
   }
-  if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
-      (errno != EINPROGRESS))
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "connect to `%s' failed: %s",
-                address,
-                strerror (errno));
-    GNUNET_NETWORK_socket_close (sock);
-    GNUNET_free (in);
-    return GNUNET_SYSERR;
-  }
+    struct GNUNET_NETWORK_Handle *sock;
+    struct Queue *queue;
 
-  queue = GNUNET_new (struct Queue);
-  queue->target = *peer;
-  queue->address = in;
-  queue->address_len = in_len;
-  queue->sock = sock;
-  queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
-  boot_queue (queue);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "booted queue with target %s\n",
-              GNUNET_i2s (&queue->target));
-  // queue->mq_awaits_continue = GNUNET_YES;
-  queue->read_task =
-    GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                                   queue->sock,
-                                   &queue_read_kx,
-                                   queue);
+    sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 
IPPROTO_TCP);
+    if (NULL == sock)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "socket(%d) failed: %s",
+                  in->sa_family,
+                  strerror (errno));
+      GNUNET_free (in);
+      return GNUNET_SYSERR;
+    }
+    if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
+        (errno != EINPROGRESS))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "connect to `%s' failed: %s",
+                  address,
+                  strerror (errno));
+      GNUNET_NETWORK_socket_close (sock);
+      GNUNET_free (in);
+      return GNUNET_SYSERR;
+    }
 
+    queue = GNUNET_new (struct Queue);
+    queue->target = *peer;
+    queue->address = in;
+    queue->address_len = in_len;
+    queue->sock = sock;
+    queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
+    boot_queue (queue);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "booted queue with target %s\n",
+                GNUNET_i2s (&queue->target));
+    // queue->mq_awaits_continue = GNUNET_YES;
+    queue->read_task =
+      GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                     queue->sock,
+                                     &queue_read_kx,
+                                     queue);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "start kx mq_init\n");
 
-  start_initial_kx_out (queue);
-  queue->write_task =
-    GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                    queue->sock,
-                                    &queue_write,
-                                    queue);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "start kx mq_init\n");
+
+    start_initial_kx_out (queue);
+    queue->write_task =
+      GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      queue->sock,
+                                      &queue_write,
+                                      queue);
+  }
+
   return GNUNET_OK;
 }
 
@@ -3062,6 +3436,7 @@ get_lt_delete_it (void *cls,
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lt->listen_sock));
     lt->listen_sock = NULL;
   }
+  GNUNET_free (lt);
   return GNUNET_OK;
 }
 
@@ -3112,7 +3487,10 @@ do_shutdown (void *cls)
     GNUNET_NAT_unregister (nat);
     nat = NULL;
   }
+  GNUNET_CONTAINER_multihashmap_iterate (pending_reversals, 
&pending_reversals_delete_it, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (pending_reversals);
   GNUNET_CONTAINER_multihashmap_iterate (lt_map, &get_lt_delete_it, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (lt_map);
   GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, 
NULL);
   GNUNET_CONTAINER_multipeermap_destroy (queue_map);
   if (NULL != ch)
@@ -3454,7 +3832,7 @@ nat_register ()
                              (const struct sockaddr **) saddrs,
                              saddr_lens,
                              &nat_address_cb,
-                             NULL /* FIXME: support reversal: #5529 */,
+                             try_connection_reversal,
                              NULL /* closure */);
   for (i = addrs_lens - 1; i >= 0; i--)
     GNUNET_free (saddrs[i]);
@@ -3554,6 +3932,8 @@ run (void *cls,
   socklen_t addr_len_ipv6;
 
   (void) cls;
+
+  pending_reversals = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
   memset (&v4,0,sizeof(struct sockaddr_in));
   memset (&v6,0,sizeof(struct sockaddr_in6));
   cfg = c;
@@ -3647,6 +4027,7 @@ run (void *cls,
                                                    GNUNET_TIME_UNIT_MINUTES,
                                                    &init_socket_resolv,
                                                    &port);
+
   GNUNET_free (bindto);
   GNUNET_free (start);
 }
diff --git a/src/transport/gnunet-communicator-udp.c 
b/src/transport/gnunet-communicator-udp.c
index 282902f1c..6b2985b59 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -3735,6 +3735,13 @@ do_broadcast (void *cls)
                                                  NULL);
 }
 
+static void
+try_connection_reversal (void *cls,
+                         const struct sockaddr *addr,
+                         socklen_t addrlen)
+{
+  /* FIXME: support reversal: #5529 */
+}
 
 /**
  * Setup communicator and launch network interactions.
@@ -3915,7 +3922,7 @@ run (void *cls,
                              (const struct sockaddr **) &in,
                              &in_len,
                              &nat_address_cb,
-                             NULL /* FIXME: support reversal: #5529 */,
+                             try_connection_reversal,
                              NULL /* closure */);
 }
 
diff --git a/src/transport/gnunet-service-tng.c 
b/src/transport/gnunet-service-tng.c
index 5a28efb66..21aa46947 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -800,10 +800,7 @@ struct TransportDVBoxMessage
   /**
    * Size this msg had initially. This is needed to calculate the hmac at the 
target.
    * The header size can not be used for that, because the box size is getting 
smaller at each hop.
-   */
-  /**
-   * The length of the struct (in bytes, including the length field itself),
-   * in big-endian format.
+   *
    */
   uint16_t orig_size GNUNET_PACKED;
 
@@ -10383,9 +10380,10 @@ suggest_to_connect (const struct GNUNET_PeerIdentity 
*pid, const char *address)
   }
   /* forward suggestion for queue creation to communicator */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Request #%u for `%s' communicator to create queue to `%s'\n",
+              "Request #%u for `%s' communicator to create queue to `%s' at 
`%s'\n",
               (unsigned int) idgen,
               prefix,
+              GNUNET_i2s (pid),
               address);
   GNUNET_free (prefix);
   alen = strlen (address) + 1;
@@ -10660,6 +10658,30 @@ start_dv_learn (void *cls)
 }
 
 
+/**
+ * Get the IP address without the port number.
+ *
+ * @param address The string contains a communicator prefix, IP address and 
port
+ *        like this 'tcp-92.68.150.1:55452'.
+ * @return String with IP address only.
+ */
+static char *
+get_address_without_port (const char *address)
+{
+  const char *colon;
+  char *colon_rest;
+  size_t colon_rest_length;
+  char *address_without_port;
+
+  colon = strchr (address,':');
+  colon_rest = GNUNET_strndup (address, colon - address);
+  colon_rest_length = strlen (colon_rest);
+  address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 
4);
+  GNUNET_free (colon_rest);
+
+  return address_without_port;
+}
+
 /**
  * A new queue has been created, check if any address validation
  * requests have been waiting for it.
@@ -10676,16 +10698,31 @@ check_validation_request_pending (void *cls,
 {
   struct Queue *q = cls;
   struct ValidationState *vs = value;
+  char *address_without_port_vs;
+  char *address_without_port_q;
+  int success = GNUNET_YES;
 
+  address_without_port_vs = get_address_without_port (vs->address);
+  address_without_port_q = get_address_without_port (q->address);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Check validation request pending for `%s' at `%s'/`%s' 
(vs)/(q)\n",
+              GNUNET_i2s (pid),
+              address_without_port_vs,
+              address_without_port_q);
   (void) pid;
   if ((GNUNET_YES == vs->awaiting_queue) &&
-      (0 == strcmp (vs->address, q->address)))
+      (0 == strcmp (address_without_port_vs, address_without_port_q)))
   {
+    
     vs->awaiting_queue = GNUNET_NO;
     validation_transmit_on_queue (q, vs);
-    return GNUNET_NO;
+    success = GNUNET_NO;
   }
-  return GNUNET_OK;
+
+  GNUNET_free (address_without_port_vs);
+  GNUNET_free (address_without_port_q);
+  return success;
 }
 
 
diff --git a/src/transport/test_transport_nat_icmp_tcp_topo.conf 
b/src/transport/test_transport_nat_icmp_tcp_topo.conf
new file mode 100644
index 000000000..37738c80f
--- /dev/null
+++ b/src/transport/test_transport_nat_icmp_tcp_topo.conf
@@ -0,0 +1,7 @@
+M:1
+N:1
+X:1
+T:libgnunet_test_transport_plugin_cmd_nat_upnp
+K:1|{connect:{P:1:1:tcp_natted}}
+R:1|{tcp_port:0}|{udp_port:0}
+P:1:1
\ No newline at end of file
diff --git a/src/transport/transport_api2_communication.c 
b/src/transport/transport_api2_communication.c
index b79f0d8bf..079982ca5 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -1048,21 +1048,10 @@ GNUNET_TRANSPORT_communicator_address_remove (
   struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch;
 
   send_del_address (ai);
-  if (NULL == ai->prev)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "prev null\n");
-  if (ch->ai_head == ai)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "equals head\n");
-  if (NULL == ai->next)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "next null\n");
-  if (ch->ai_tail == ai)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "equals tail\n");
   GNUNET_CONTAINER_DLL_remove (ch->ai_head, ch->ai_tail, ai);
   GNUNET_free (ai->address);
   GNUNET_free (ai);
+  ai = NULL;
 }
 
 /**
@@ -1074,9 +1063,13 @@ void
 GNUNET_TRANSPORT_communicator_address_remove_all (
   struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
 {
-  for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai;
-       ai = ai->next)
+  struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head;
+  while (NULL != ai)
+  {
+    struct GNUNET_TRANSPORT_AddressIdentifier *ai_next = ai->next;
     GNUNET_TRANSPORT_communicator_address_remove (ai);
+    ai = ai_next;
+  }
 }
 
 
diff --git a/src/transport/transport_api_cmd_connecting_peers.c 
b/src/transport/transport_api_cmd_connecting_peers.c
index d399e9d0a..7feecbcc7 100644
--- a/src/transport/transport_api_cmd_connecting_peers.c
+++ b/src/transport/transport_api_cmd_connecting_peers.c
@@ -97,6 +97,13 @@ connect_peers_run (void *cls,
                                          pos_prefix->address_prefix);
       if (NULL != addr)
       {
+        char *natted_p = strstr (pos_prefix->address_prefix, "_");
+
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "0 validating peer number %s %s %s\n",
+                    natted_p,
+                    pos_prefix->address_prefix,
+                    addr);
         if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp"))
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "validating memcmp\n");
@@ -108,10 +115,28 @@ connect_peers_run (void *cls,
           GNUNET_asprintf (&addr_and_port,
                            "%s:2086",
                            addr);
-        else
+        else if (NULL == natted_p)
           GNUNET_asprintf (&addr_and_port,
                            "%s:60002",
                            addr);
+        else if (NULL != natted_p)
+        {
+          char *prefix;
+          char *rest;
+          char *rest2;
+          char *address;
+
+          prefix = strtok(addr, "_");
+          rest = strtok(NULL, "_");
+          rest2 = strtok(rest, "-");
+          address = strtok(NULL, "-");
+
+          GNUNET_asprintf (&addr_and_port,
+                           "%s-%s:0",
+                           prefix,
+                           address);
+
+        }
         peer = GNUNET_TESTING_get_peer (num, tl_system);
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "validating peer number %u with identity %s and address %s 
%u %s\n",
diff --git a/src/transport/transport_api_cmd_start_peer.c 
b/src/transport/transport_api_cmd_start_peer.c
index 516f8d0aa..1f8ef2f8f 100644
--- a/src/transport/transport_api_cmd_start_peer.c
+++ b/src/transport/transport_api_cmd_start_peer.c
@@ -244,6 +244,7 @@ start_peer_run (void *cls,
                                          "UNIXPATH",
                                          udp_communicator_unix_path);
 
+
   system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
                                                           sps->system_label);
   GNUNET_TESTING_get_trait_test_system (system_cmd,
@@ -384,11 +385,12 @@ start_peer_cleanup (void *cls)
     GNUNET_free (sps->handlers);
     sps->handlers = NULL;
   }
-  if (NULL != sps->cfg)
+  //TODO Investigate why this caused problems during shutdown.
+  /*if (NULL != sps->cfg)
   {
     GNUNET_CONFIGURATION_destroy (sps->cfg);
     sps->cfg = NULL;
-  }
+    }*/
   GNUNET_free (sps->cfgname);
   GNUNET_free (sps->node_ip);
   GNUNET_free (sps->system_label);
diff --git a/src/util/mq.c b/src/util/mq.c
index 788b9b636..de0cff0c2 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -304,10 +304,6 @@ void
 GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
                 struct GNUNET_MQ_Envelope *ev)
 {
-  if (NULL == mq)
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "mq is NUll when sending message of type %u\n",
-                (unsigned int) ntohs (ev->mh->type));
   GNUNET_assert (NULL != mq);
   GNUNET_assert (NULL == ev->parent_queue);
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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