aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-02-01 18:58:40 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2023-02-01 18:58:40 +0900
commit0effaa71dc569a1c7ecd97d065638b5c75bdba5e (patch)
treefdb25600105c211035a626145b73dbf1996de6cd
parentac40efdae723f850bfff62c0cddad130a37f425e (diff)
parent2652a92f5417b38e059e4d24ace9fb7328e0abdb (diff)
downloadgnunet-0effaa71dc569a1c7ecd97d065638b5c75bdba5e.tar.gz
gnunet-0effaa71dc569a1c7ecd97d065638b5c75bdba5e.zip
Merge remote-tracking branch 'origin/master'
-rwxr-xr-xcontrib/netjail/netjail_core.sh14
-rwxr-xr-xcontrib/netjail/netjail_start.sh34
-rw-r--r--src/testing/testing.c22
-rw-r--r--src/testing/testing_api_cmd_netjail_start_cmds_helper.c4
-rw-r--r--src/transport/Makefile.am2
-rw-r--r--src/transport/gnunet-communicator-tcp.c729
-rw-r--r--src/transport/gnunet-communicator-udp.c9
-rw-r--r--src/transport/gnunet-service-tng.c53
-rw-r--r--src/transport/test_transport_nat_icmp_tcp_topo.conf7
-rw-r--r--src/transport/transport_api2_communication.c21
-rw-r--r--src/transport/transport_api_cmd_connecting_peers.c27
-rw-r--r--src/transport/transport_api_cmd_start_peer.c6
-rw-r--r--src/util/mq.c4
13 files changed, 707 insertions, 225 deletions
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() {
145 local BRIDGE=$2 145 local BRIDGE=$2
146 local ADDRESS=$3 146 local ADDRESS=$3
147 local MASK=$4 147 local MASK=$4
148 148
149 netjail_next_interface 149 netjail_next_interface
150 local NUM_IF=$RESULT 150 local NUM_IF=$RESULT
151 netjail_next_interface 151 netjail_next_interface
152 local NUM_BR=$RESULT 152 local NUM_BR=$RESULT
153 153
154 local LINK_IF=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_IF) 154 local LINK_IF=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_IF)
155 local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_BR) 155 local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_BR)
156 156
@@ -163,18 +163,18 @@ netjail_node_link_bridge() {
163 ip -n $NODE link set up dev lo 163 ip -n $NODE link set up dev lo
164 164
165 ip link set $LINK_BR up 165 ip link set $LINK_BR up
166 166
167 RESULT=$LINK_BR 167 RESULT=$LINK_IF
168} 168}
169 169
170netjail_node_link_bridge_name() { 170netjail_node_link_bridge_name() {
171 171
172 netjail_next_interface 172 netjail_next_interface
173 netjail_next_interface 173 netjail_next_interface
174 local NUM_BR=$RESULT 174 local NUM_BR=$RESULT
175 175
176 local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_BR) 176 local LINK_BR=$(printf $INTERFACE_FORMAT_STRING $PREPREFIX $PREFIX $NUM_BR)
177 177
178 RESULT=$LINK_BR 178 RESULT=$LINK_BR
179} 179}
180 180
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
52 KNOWN_NODES[$X]=$RESULT 52 KNOWN_NODES[$X]=$RESULT
53 netjail_node_link_bridge ${KNOWN_NODES[$X]} $NETWORK_NET "$KNOWN_GROUP.$X" 16 53 netjail_node_link_bridge ${KNOWN_NODES[$X]} $NETWORK_NET "$KNOWN_GROUP.$X" 16
54 KNOWN_LINKS[$X]=$RESULT 54 KNOWN_LINKS[$X]=$RESULT
55
56 # Execute echo 1 > /proc/sys/net/netfilter/nf_log_all_netns to make itables log to the host.
57 #ip netns exec ${KNOWN_NODES[$X]} iptables -A INPUT -j LOG --log-prefix '** Known ${KNOWN_NODES[$X]} **'
58 #ip netns exec ${KNOWN_NODES[$X]} iptables -A OUTPUT -j LOG --log-prefix '** Known ${KNOWN_NODES[$X]} **'
59 ip netns exec ${KNOWN_NODES[$X]} iptables -A OUTPUT -p icmp -j ACCEPT
60 ip netns exec ${KNOWN_NODES[$X]} iptables -A INPUT -p icmp -j ACCEPT
61
55done 62done
56 63
57declare -A NODES 64declare -A NODES
@@ -61,18 +68,36 @@ for N in $(seq $GLOBAL_N); do
61 netjail_node 68 netjail_node
62 ROUTERS[$N]=$RESULT 69 ROUTERS[$N]=$RESULT
63 netjail_node_link_bridge ${ROUTERS[$N]} $NETWORK_NET "$GLOBAL_GROUP.$N" 16 70 netjail_node_link_bridge ${ROUTERS[$N]} $NETWORK_NET "$GLOBAL_GROUP.$N" 16
64 NETWORK_LINKS[$N]=$RESULT 71 ROUTER_EXT_IF[$N]=$RESULT
65 netjail_bridge 72 netjail_bridge
66 ROUTER_NETS[$N]=$RESULT 73 ROUTER_NETS[$N]=$RESULT
67 74
75 #ip netns exec ${ROUTERS[$N]} iptables -A INPUT -j LOG --log-prefix '** Router ${ROUTERS[$N]} **'
76 ip netns exec ${ROUTERS[$N]} iptables -A INPUT -p icmp -j ACCEPT
77 ip netns exec ${ROUTERS[$N]} iptables -t nat -A PREROUTING -p icmp -d $GLOBAL_GROUP.$N -j DNAT --to $LOCAL_GROUP.1
78 ip netns exec ${ROUTERS[$N]} iptables -A FORWARD -p icmp -d $LOCAL_GROUP.1 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
79 #ip netns exec ${ROUTERS[$N]} iptables -A OUTPUT -j LOG --log-prefix '** Router ${ROUTERS[$N]} **'
80 ip netns exec ${ROUTERS[$N]} iptables -A OUTPUT -p icmp -j ACCEPT
81
68 for M in $(seq $LOCAL_M); do 82 for M in $(seq $LOCAL_M); do
69 netjail_node 83 netjail_node
70 NODES[$N,$M]=$RESULT 84 NODES[$N,$M]=$RESULT
71 netjail_node_link_bridge ${NODES[$N,$M]} ${ROUTER_NETS[$N]} "$LOCAL_GROUP.$M" 24 85 netjail_node_link_bridge ${NODES[$N,$M]} ${ROUTER_NETS[$N]} "$LOCAL_GROUP.$M" 24
72 NODE_LINKS[$N,$M]=$RESULT 86 NODE_LINKS[$N,$M]=$RESULT
87
88 #ip netns exec ${NODES[$N,$M]} iptables -A INPUT -j LOG --log-prefix '** Node ${NODES[$N,$M]} **'
89 #ip netns exec ${NODES[$N,$M]} iptables -A OUTPUT -j LOG --log-prefix '** Node ${NODES[$N,$M]} **'
90 ip netns exec ${NODES[$N,$M]} iptables -A OUTPUT -p icmp -j ACCEPT
91 ip netns exec ${NODES[$N,$M]} iptables -A INPUT -p icmp -j ACCEPT
73 done 92 done
74 93
75 ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))" 94 ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))"
95
96 let X=$KNOWN+1
97 ip netns exec ${ROUTERS[$N]} ip route add "$KNOWN_GROUP.$X" dev ${ROUTER_EXT_IF[$N]}
98 ip netns exec ${ROUTERS[$N]} ip route add default via "$KNOWN_GROUP.$X"
99
100
76 netjail_node_link_bridge ${ROUTERS[$N]} ${ROUTER_NETS[$N]} $ROUTER_ADDR 24 101 netjail_node_link_bridge ${ROUTERS[$N]} ${ROUTER_NETS[$N]} $ROUTER_ADDR 24
77 ROUTER_LINKS[$N]=$RESULT 102 ROUTER_LINKS[$N]=$RESULT
78 103
@@ -135,3 +160,8 @@ for N in $(seq $GLOBAL_N); do
135 ip netns exec ${ROUTERS[$N]} ./${R_SCRIPT[$N]} ${ROUTER_NETS[$N]} 1 160 ip netns exec ${ROUTERS[$N]} ./${R_SCRIPT[$N]} ${ROUTER_NETS[$N]} 1
136 fi 161 fi
137done 162done
163
164# We like to have a node acting as a gateway for all router nodes. This is especially needed for sending fake ICMP packets.
165netjail_node
166GATEWAY=$RESULT
167netjail_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 @@
63 63
64#define PREFIX_UDP "udp" 64#define PREFIX_UDP "udp"
65 65
66#define PREFIX_TCP_NATTED "tcp_natted"
67
68#define PREFIX_UDP_NATTED "udp_natted"
69
66/** 70/**
67 * Lowest port used for GNUnet testing. Should be high enough to not 71 * Lowest port used for GNUnet testing. Should be high enough to not
68 * conflict with other applications running on the hosts but be low 72 * conflict with other applications running on the hosts but be low
@@ -1914,7 +1918,7 @@ get_value (const char *key, const char *line)
1914 * Every line in the topology configuration starts with a string indicating which 1918 * Every line in the topology configuration starts with a string indicating which
1915 * kind of information will be configured with this line. Configuration values following 1919 * kind of information will be configured with this line. Configuration values following
1916 * this string are seperated by special sequences of characters. A value might be 1920 * this string are seperated by special sequences of characters. A value might be
1917 * a key value pair. A special key is the 'connect' which can appear more than once. 1921 * a key value pair. A special key is the 'connect' key which can appear more than once.
1918 * The value is the information about a connection via some protocol to some other node. 1922 * The value is the information about a connection via some protocol to some other node.
1919 * This function returns the struct GNUNET_TESTING_NodeConnection which holds the information 1923 * This function returns the struct GNUNET_TESTING_NodeConnection which holds the information
1920 * of the connect value. 1924 * of the connect value.
@@ -2419,7 +2423,8 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2419 unsigned int node_n; 2423 unsigned int node_n;
2420 2424
2421 LOG (GNUNET_ERROR_TYPE_DEBUG, 2425 LOG (GNUNET_ERROR_TYPE_DEBUG,
2422 "node_n: %u\n", 2426 "get address prefix: %s node_n: %u\n",
2427 prefix,
2423 connection->node_n); 2428 connection->node_n);
2424 2429
2425 node = connection->node; 2430 node = connection->node;
@@ -2443,15 +2448,10 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2443 return NULL; 2448 return NULL;
2444 } 2449 }
2445 2450
2446 if (0 == strcmp (PREFIX_TCP, prefix)) 2451 if (0 == strcmp (PREFIX_TCP, prefix) ||
2447 { 2452 0 == strcmp (PREFIX_UDP, prefix) ||
2448 2453 0 == strcmp (PREFIX_UDP_NATTED, prefix) ||
2449 GNUNET_asprintf (&addr, 2454 0 == strcmp (PREFIX_TCP_NATTED, prefix))
2450 template,
2451 prefix,
2452 node_n);
2453 }
2454 else if (0 == strcmp (PREFIX_UDP, prefix))
2455 { 2455 {
2456 GNUNET_asprintf (&addr, 2456 GNUNET_asprintf (&addr,
2457 template, 2457 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)
489 } else if (ns->number_of_local_tests_finished == total_number) 489 } else if (ns->number_of_local_tests_finished == total_number)
490 { 490 {
491 GNUNET_SCHEDULER_cancel (ns->timeout_task); 491 GNUNET_SCHEDULER_cancel (ns->timeout_task);
492 ns->timeout_task = NULL;
492 GNUNET_TESTING_async_finish (&ns->ac); 493 GNUNET_TESTING_async_finish (&ns->ac);
493 } 494 }
494 break; 495 break;
@@ -525,7 +526,8 @@ exp_cb (void *cls)
525 struct NetJailState *ns = cls; 526 struct NetJailState *ns = cls;
526 527
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n"); 528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
528 GNUNET_SCHEDULER_cancel (ns->timeout_task); 529 if (NULL != ns->timeout_task)
530 GNUNET_SCHEDULER_cancel (ns->timeout_task);
529 GNUNET_TESTING_async_fail (&(ns->ac)); 531 GNUNET_TESTING_async_fail (&(ns->ac));
530} 532}
531 533
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
760# Only test TNG if we run experimental 760# Only test TNG if we run experimental
761if HAVE_EXPERIMENTAL 761if HAVE_EXPERIMENTAL
762check_SCRIPTS= \ 762check_SCRIPTS= \
763test_transport_nat_icmp_tcp.sh \
763 test_transport_nat_upnp.sh \ 764 test_transport_nat_upnp.sh \
764 test_transport_simple_send_string.sh \ 765 test_transport_simple_send_string.sh \
765 test_transport_simple_send.sh \ 766 test_transport_simple_send.sh \
@@ -1509,6 +1510,7 @@ test_transport_api_slow_ats_LDADD = \
1509 1510
1510 1511
1511EXTRA_DIST = \ 1512EXTRA_DIST = \
1513test_transport_nat_icmp_tcp.sh \
1512test_transport_nat_upnp.sh \ 1514test_transport_nat_upnp.sh \
1513test_transport_simple_send_string.sh \ 1515test_transport_simple_send_string.sh \
1514test_transport_simple_send.sh \ 1516test_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 @@
40#include "gnunet_transport_communication_service.h" 40#include "gnunet_transport_communication_service.h"
41#include "gnunet_resolver_service.h" 41#include "gnunet_resolver_service.h"
42 42
43
44/**
45 * How long until we give up on establishing an NAT connection?
46 * Must be > 4 RTT
47 */
48#define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
49
43/** 50/**
44 * How long do we believe our addresses to remain up (before 51 * How long do we believe our addresses to remain up (before
45 * the other peer should revalidate). 52 * the other peer should revalidate).
@@ -364,10 +371,47 @@ struct TCPFinish
364 struct GNUNET_ShortHashCode hmac; 371 struct GNUNET_ShortHashCode hmac;
365}; 372};
366 373
374/**
375 * Basically a WELCOME message, but with the purpose
376 * of giving the waiting peer a client handle to use
377 */
378struct TCPNATProbeMessage
379{
380 /**
381 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
382 */
383 struct GNUNET_MessageHeader header;
384
385 /**
386 * Identity of the sender of the message.
387 */
388 struct GNUNET_PeerIdentity clientIdentity;
389};
367 390
368GNUNET_NETWORK_STRUCT_END 391GNUNET_NETWORK_STRUCT_END
369 392
370/** 393/**
394 * Struct for pending nat reversals.
395 */
396struct PendingReversal
397{
398 /*
399 * Timeout task.
400 */
401 struct GNUNET_SCHEDULER_Task *timeout_task;
402
403 /**
404 * To whom are we like to talk to.
405 */
406 struct GNUNET_PeerIdentity target;
407
408 /**
409 * Address the reversal was send to.
410 */
411 struct sockaddr *in;
412};
413
414/**
371 * Struct to use as closure. 415 * Struct to use as closure.
372 */ 416 */
373struct ListenTask 417struct ListenTask
@@ -653,6 +697,21 @@ struct ProtoQueue
653 struct GNUNET_NETWORK_Handle *sock; 697 struct GNUNET_NETWORK_Handle *sock;
654 698
655 /** 699 /**
700 * ID of write task for this connection.
701 */
702 struct GNUNET_SCHEDULER_Task *write_task;
703
704 /**
705 * buffer for writing struct TCPNATProbeMessage to network.
706 */
707 char write_buf[sizeof (struct TCPNATProbeMessage)];
708
709 /**
710 * Offset of the buffer?
711 */
712 size_t write_off;
713
714 /**
656 * ID of read task for this connection. 715 * ID of read task for this connection.
657 */ 716 */
658 struct GNUNET_SCHEDULER_Task *read_task; 717 struct GNUNET_SCHEDULER_Task *read_task;
@@ -856,6 +915,11 @@ int shutdown_running = GNUNET_NO;
856unsigned int bind_port; 915unsigned int bind_port;
857 916
858/** 917/**
918 * Map of pending reversals.
919 */
920struct GNUNET_CONTAINER_MultiHashMap *pending_reversals;
921
922/**
859 * We have been notified that our listen socket has something to 923 * We have been notified that our listen socket has something to
860 * read. Do the read and reschedule this function to be called again 924 * read. Do the read and reschedule this function to be called again
861 * once more is available. 925 * once more is available.
@@ -1568,6 +1632,134 @@ inject_rekey (struct Queue *queue)
1568 setup_out_cipher (queue); 1632 setup_out_cipher (queue);
1569} 1633}
1570 1634
1635static int
1636pending_reversals_delete_it (void *cls,
1637 const struct GNUNET_HashCode *key,
1638 void *value)
1639{
1640 (void) cls;
1641 struct PendingReversal *pending_reversal = value;
1642
1643 if (NULL != pending_reversal->timeout_task)
1644 {
1645 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1646 pending_reversal->timeout_task = NULL;
1647 }
1648 GNUNET_CONTAINER_multihashmap_remove (pending_reversals,
1649 key,
1650 pending_reversal);
1651 GNUNET_free (pending_reversal->in);
1652 GNUNET_free (pending_reversal);
1653 return GNUNET_OK;
1654}
1655
1656
1657static void
1658check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family, struct GNUNET_PeerIdentity *sender)
1659{
1660 if (AF_INET == sa_family)
1661 {
1662 struct PendingReversal *pending_reversal;
1663 struct GNUNET_HashCode key;
1664 struct sockaddr_in *natted_address;
1665
1666 natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
1667 natted_address->sin_port = 0;
1668 GNUNET_CRYPTO_hash (natted_address,
1669 sizeof(struct sockaddr),
1670 &key);
1671
1672 pending_reversal = GNUNET_CONTAINER_multihashmap_get (pending_reversals,
1673 &key);
1674 if (NULL != pending_reversal && (NULL == sender ||
1675 0 != memcmp (sender, &pending_reversal->target, sizeof(struct GNUNET_PeerIdentity))))
1676 {
1677 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1678 "Removing invalid pending reversal for `%s'at `%s'\n",
1679 GNUNET_i2s (&pending_reversal->target),
1680 GNUNET_a2s (in, sizeof (in)));
1681 pending_reversals_delete_it (NULL, &key, pending_reversal);
1682 }
1683 GNUNET_free (natted_address);
1684 }
1685}
1686
1687
1688/**
1689 * Closes socket and frees memory associated with @a pq.
1690 *
1691 * @param pq proto queue to free
1692 */
1693static void
1694free_proto_queue (struct ProtoQueue *pq)
1695{
1696 if (NULL != pq->listen_sock)
1697 {
1698 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock));
1699 pq->listen_sock = NULL;
1700 }
1701 if (NULL != pq->read_task)
1702 {
1703 GNUNET_SCHEDULER_cancel (pq->read_task);
1704 pq->read_task = NULL;
1705 }
1706 if (NULL != pq->write_task)
1707 {
1708 GNUNET_SCHEDULER_cancel (pq->write_task);
1709 pq->write_task = NULL;
1710 }
1711 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, NULL);
1712 GNUNET_NETWORK_socket_close (pq->sock);
1713 GNUNET_free (pq->address);
1714 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
1715 GNUNET_free (pq);
1716}
1717
1718
1719/**
1720 * We have been notified that our socket is ready to write.
1721 * Then reschedule this function to be called again once more is available.
1722 *
1723 * @param cls a `struct ProtoQueue`
1724 */
1725static void
1726proto_queue_write (void *cls)
1727{
1728 struct ProtoQueue *pq = cls;
1729 ssize_t sent;
1730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1731 pq->write_task = NULL;
1732 if (0 != pq->write_off)
1733 {
1734 sent = GNUNET_NETWORK_socket_send (pq->sock,
1735 pq->write_buf,
1736 pq->write_off);
1737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1738 "Sent %lu bytes to TCP queue\n", sent);
1739 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1740 {
1741 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
1742 free_proto_queue (pq);
1743 return;
1744 }
1745 if (sent > 0)
1746 {
1747 size_t usent = (size_t) sent;
1748 pq->write_off -= usent;
1749 memmove (pq->write_buf,
1750 &pq->write_buf[usent],
1751 pq->write_off);
1752 }
1753 }
1754 /* do we care to write more? */
1755 if ((0 < pq->write_off))
1756 pq->write_task =
1757 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1758 pq->sock,
1759 &proto_queue_write,
1760 pq);
1761}
1762
1571 1763
1572/** 1764/**
1573 * We have been notified that our socket is ready to write. 1765 * We have been notified that our socket is ready to write.
@@ -1779,6 +1971,10 @@ try_handle_plaintext (struct Queue *queue)
1779 &queue_write, 1971 &queue_write,
1780 queue); 1972 queue);
1781 } 1973 }
1974 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
1975 {
1976 check_and_remove_pending_reversal (queue->address, queue->address->sa_family, NULL);
1977 }
1782 1978
1783 unverified_size = -1; 1979 unverified_size = -1;
1784 1980
@@ -2659,22 +2855,99 @@ decrypt_and_check_tc (struct Queue *queue,
2659 2855
2660 2856
2661/** 2857/**
2662 * Closes socket and frees memory associated with @a pq. 2858 * Read from the socket of the queue until we have enough data
2859 * to initialize the decryption logic and can switch to regular
2860 * reading.
2663 * 2861 *
2664 * @param pq proto queue to free 2862 * @param cls a `struct Queue`
2665 */ 2863 */
2666static void 2864static void
2667free_proto_queue (struct ProtoQueue *pq) 2865queue_read_kx (void *cls)
2668{ 2866{
2669 if (NULL != pq->listen_sock) 2867 struct Queue *queue = cls;
2868 ssize_t rcvd;
2869 struct GNUNET_TIME_Relative left;
2870 struct TCPConfirmation tc;
2871
2872 queue->read_task = NULL;
2873 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2874 if (0 == left.rel_value_us)
2670 { 2875 {
2671 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock)); 2876 queue_destroy (queue);
2672 pq->listen_sock = NULL; 2877 return;
2673 } 2878 }
2674 GNUNET_NETWORK_socket_close (pq->sock); 2879 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2675 GNUNET_free (pq->address); 2880 &queue->cread_buf[queue->cread_off],
2676 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); 2881 BUF_SIZE - queue->cread_off);
2677 GNUNET_free (pq); 2882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2883 "Received %lu bytes for KX\n",
2884 rcvd);
2885 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
2886 "transport",
2887 "Received %lu bytes for KX\n",
2888 rcvd);
2889 if (-1 == rcvd)
2890 {
2891 if ((EAGAIN != errno) && (EINTR != errno))
2892 {
2893 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
2894 queue_destroy (queue);
2895 return;
2896 }
2897 queue->read_task =
2898 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
2899 return;
2900 }
2901 queue->cread_off += rcvd;
2902 if (queue->cread_off < INITIAL_KX_SIZE)
2903 {
2904 /* read more */
2905 queue->read_task =
2906 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
2907 return;
2908 }
2909 /* we got all the data, let's find out who we are talking to! */
2910 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *)
2911 queue->cread_buf,
2912 queue);
2913 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
2914 {
2915 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2916 "Invalid TCP KX received from %s\n",
2917 GNUNET_a2s (queue->address, queue->address_len));
2918 queue_destroy (queue);
2919 return;
2920 }
2921 if (0 !=
2922 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
2923 {
2924 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2925 "Invalid sender in TCP KX received from %s\n",
2926 GNUNET_a2s (queue->address, queue->address_len));
2927 queue_destroy (queue);
2928 return;
2929 }
2930 send_challenge (tc.challenge, queue);
2931 queue->write_task =
2932 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2933 queue->sock,
2934 &queue_write,
2935 queue);
2936
2937 /* update queue timeout */
2938 reschedule_queue_timeout (queue);
2939 /* prepare to continue with regular read task immediately */
2940 memmove (queue->cread_buf,
2941 &queue->cread_buf[INITIAL_KX_SIZE],
2942 queue->cread_off - (INITIAL_KX_SIZE));
2943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2944 "cread_off is %lu bytes before adjusting\n",
2945 queue->cread_off);
2946 queue->cread_off -= INITIAL_KX_SIZE;
2947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2948 "cread_off set to %lu bytes\n",
2949 queue->cread_off);
2950 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
2678} 2951}
2679 2952
2680 2953
@@ -2692,6 +2965,7 @@ proto_read_kx (void *cls)
2692 struct GNUNET_TIME_Relative left; 2965 struct GNUNET_TIME_Relative left;
2693 struct Queue *queue; 2966 struct Queue *queue;
2694 struct TCPConfirmation tc; 2967 struct TCPConfirmation tc;
2968 GNUNET_SCHEDULER_TaskCallback read_task;
2695 2969
2696 pq->read_task = NULL; 2970 pq->read_task = NULL;
2697 left = GNUNET_TIME_absolute_get_remaining (pq->timeout); 2971 left = GNUNET_TIME_absolute_get_remaining (pq->timeout);
@@ -2704,10 +2978,10 @@ proto_read_kx (void *cls)
2704 &pq->ibuf[pq->ibuf_off], 2978 &pq->ibuf[pq->ibuf_off],
2705 sizeof(pq->ibuf) - pq->ibuf_off); 2979 sizeof(pq->ibuf) - pq->ibuf_off);
2706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2707 "Received %lu bytes for KX\n", rcvd); 2981 "Proto received %lu bytes for KX\n", rcvd);
2708 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, 2982 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
2709 "transport", 2983 "transport",
2710 "Received %lu bytes for KX\n", rcvd); 2984 "Proto received %lu bytes for KX\n", rcvd);
2711 if (-1 == rcvd) 2985 if (-1 == rcvd)
2712 { 2986 {
2713 if ((EAGAIN != errno) && (EINTR != errno)) 2987 if ((EAGAIN != errno) && (EINTR != errno))
@@ -2722,30 +2996,46 @@ proto_read_kx (void *cls)
2722 return; 2996 return;
2723 } 2997 }
2724 pq->ibuf_off += rcvd; 2998 pq->ibuf_off += rcvd;
2725 if (pq->ibuf_off > sizeof(pq->ibuf)) 2999 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3000 {
3001 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3002
3003 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, &pm->clientIdentity);
3004
3005 queue = GNUNET_new (struct Queue);
3006 queue->target = pm->clientIdentity;
3007 queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
3008 read_task = &queue_read_kx;
3009 }
3010 else if (pq->ibuf_off > sizeof(pq->ibuf))
2726 { 3011 {
2727 /* read more */ 3012 /* read more */
2728 pq->read_task = 3013 pq->read_task =
2729 GNUNET_SCHEDULER_add_read_net (left, pq->sock, &proto_read_kx, pq); 3014 GNUNET_SCHEDULER_add_read_net (left, pq->sock, &proto_read_kx, pq);
2730 return; 3015 return;
2731 } 3016 }
2732 /* we got all the data, let's find out who we are talking to! */ 3017 else
2733 queue = GNUNET_new (struct Queue);
2734 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
2735 queue);
2736 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
2737 { 3018 {
2738 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3019 /* we got all the data, let's find out who we are talking to! */
2739 "Invalid TCP KX received from %s\n", 3020 queue = GNUNET_new (struct Queue);
2740 GNUNET_a2s (pq->address, pq->address_len)); 3021 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
2741 gcry_cipher_close (queue->in_cipher); 3022 queue);
2742 GNUNET_free (queue); 3023 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
2743 free_proto_queue (pq); 3024 {
2744 return; 3025 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3026 "Invalid TCP KX received from %s\n",
3027 GNUNET_a2s (pq->address, pq->address_len));
3028 gcry_cipher_close (queue->in_cipher);
3029 GNUNET_free (queue);
3030 free_proto_queue (pq);
3031 return;
3032 }
3033 queue->target = tc.sender;
3034 queue->cs = GNUNET_TRANSPORT_CS_INBOUND;
3035 read_task = &queue_read;
2745 } 3036 }
2746 queue->address = pq->address; /* steals reference */ 3037 queue->address = pq->address; /* steals reference */
2747 queue->address_len = pq->address_len; 3038 queue->address_len = pq->address_len;
2748 queue->target = tc.sender;
2749 queue->listen_sock = pq->listen_sock; 3039 queue->listen_sock = pq->listen_sock;
2750 queue->sock = pq->sock; 3040 queue->sock = pq->sock;
2751 3041
@@ -2757,12 +3047,11 @@ proto_read_kx (void *cls)
2757 "start kx proto\n"); 3047 "start kx proto\n");
2758 3048
2759 start_initial_kx_out (queue); 3049 start_initial_kx_out (queue);
2760 queue->cs = GNUNET_TRANSPORT_CS_INBOUND;
2761 boot_queue (queue); 3050 boot_queue (queue);
2762 queue->read_task = 3051 queue->read_task =
2763 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 3052 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2764 queue->sock, 3053 queue->sock,
2765 &queue_read, 3054 read_task,
2766 queue); 3055 queue);
2767 queue->write_task = 3056 queue->write_task =
2768 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 3057 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
@@ -2777,6 +3066,51 @@ proto_read_kx (void *cls)
2777 GNUNET_free (pq); 3066 GNUNET_free (pq);
2778} 3067}
2779 3068
3069static struct ProtoQueue *
3070create_proto_queue (struct GNUNET_NETWORK_Handle *sock,
3071 struct sockaddr *in,
3072 socklen_t addrlen)
3073{
3074 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3075
3076 if (NULL == sock)
3077 {
3078 //sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3079 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3080 if (NULL == sock)
3081 {
3082 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3083 "socket(%d) failed: %s",
3084 in->sa_family,
3085 strerror (errno));
3086 GNUNET_free (in);
3087 return NULL;
3088 }
3089 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3090 (errno != EINPROGRESS))
3091 {
3092 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3093 "connect to `%s' failed: %s",
3094 GNUNET_a2s (in, addrlen),
3095 strerror (errno));
3096 GNUNET_NETWORK_socket_close (sock);
3097 GNUNET_free (in);
3098 return NULL;
3099 }
3100 }
3101 pq->address_len = addrlen;
3102 pq->address = in;
3103 pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
3104 pq->sock = sock;
3105 pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
3106 pq->sock,
3107 &proto_read_kx,
3108 pq);
3109 GNUNET_CONTAINER_DLL_insert (proto_head, proto_tail, pq);
3110
3111 return pq;
3112}
3113
2780 3114
2781/** 3115/**
2782 * We have been notified that our listen socket has something to 3116 * We have been notified that our listen socket has something to
@@ -2793,6 +3127,7 @@ listen_cb (void *cls)
2793 struct GNUNET_NETWORK_Handle *sock; 3127 struct GNUNET_NETWORK_Handle *sock;
2794 struct ProtoQueue *pq; 3128 struct ProtoQueue *pq;
2795 struct ListenTask *lt; 3129 struct ListenTask *lt;
3130 struct sockaddr *in_addr;
2796 3131
2797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2798 "listen_cb\n"); 3133 "listen_cb\n");
@@ -2819,113 +3154,71 @@ listen_cb (void *cls)
2819 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept"); 3154 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
2820 return; 3155 return;
2821 } 3156 }
2822 pq = GNUNET_new (struct ProtoQueue); 3157 in_addr = GNUNET_memdup (&in, addrlen);
2823 pq->address_len = addrlen; 3158 create_proto_queue (sock, in_addr, addrlen);
2824 pq->address = GNUNET_memdup (&in, addrlen);
2825 pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
2826 pq->sock = sock;
2827 pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
2828 pq->sock,
2829 &proto_read_kx,
2830 pq);
2831 GNUNET_CONTAINER_DLL_insert (proto_head, proto_tail, pq);
2832} 3159}
2833 3160
2834 3161
2835/**
2836 * Read from the socket of the queue until we have enough data
2837 * to initialize the decryption logic and can switch to regular
2838 * reading.
2839 *
2840 * @param cls a `struct Queue`
2841 */
2842static void 3162static void
2843queue_read_kx (void *cls) 3163try_connection_reversal (void *cls,
3164 const struct sockaddr *addr,
3165 socklen_t addrlen)
2844{ 3166{
2845 struct Queue *queue = cls; 3167 (void) cls;
2846 ssize_t rcvd; 3168 struct TCPNATProbeMessage pm;
2847 struct GNUNET_TIME_Relative left; 3169 struct ProtoQueue *pq;
2848 struct TCPConfirmation tc; 3170 struct sockaddr *in_addr;
2849 3171
2850 queue->read_task = NULL;
2851 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2852 if (0 == left.rel_value_us)
2853 {
2854 queue_destroy (queue);
2855 return;
2856 }
2857 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2858 &queue->cread_buf[queue->cread_off],
2859 BUF_SIZE - queue->cread_off);
2860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2861 "Received %lu bytes for KX\n", 3173 "addr->sa_family %d\n",
2862 rcvd); 3174 addr->sa_family);
2863 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, 3175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2864 "transport", 3176 "Try to connect back\n");
2865 "Received %lu bytes for KX\n", 3177 in_addr = GNUNET_memdup (addr, addrlen);
2866 rcvd); 3178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2867 if (-1 == rcvd) 3179 "in_addr->sa_family %d\n",
2868 { 3180 in_addr->sa_family);
2869 if ((EAGAIN != errno) && (EINTR != errno)) 3181 pq = create_proto_queue (NULL, in_addr, addrlen);
2870 { 3182 if (NULL != pq)
2871 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv"); 3183 {
2872 queue_destroy (queue); 3184 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
2873 return; 3185 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
2874 } 3186 pm.clientIdentity = my_identity;
2875 queue->read_task = 3187 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
2876 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue); 3188 pq->write_off = sizeof(struct TCPNATProbeMessage);
2877 return; 3189 pq->write_task = GNUNET_SCHEDULER_add_write_net (PROTO_QUEUE_TIMEOUT,
2878 } 3190 pq->sock,
2879 queue->cread_off += rcvd; 3191 &proto_queue_write,
2880 if (queue->cread_off < INITIAL_KX_SIZE) 3192 pq);
2881 {
2882 /* read more */
2883 queue->read_task =
2884 GNUNET_SCHEDULER_add_read_net (left, queue->sock, &queue_read_kx, queue);
2885 return;
2886 }
2887 /* we got all the data, let's find out who we are talking to! */
2888 setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *)
2889 queue->cread_buf,
2890 queue);
2891 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
2892 {
2893 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2894 "Invalid TCP KX received from %s\n",
2895 GNUNET_a2s (queue->address, queue->address_len));
2896 queue_destroy (queue);
2897 return;
2898 } 3193 }
2899 if (0 != 3194 else
2900 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
2901 { 3195 {
2902 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3196 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2903 "Invalid sender in TCP KX received from %s\n", 3197 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
2904 GNUNET_a2s (queue->address, queue->address_len));
2905 queue_destroy (queue);
2906 return;
2907 } 3198 }
2908 send_challenge (tc.challenge, queue); 3199}
2909 queue->write_task =
2910 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2911 queue->sock,
2912 &queue_write,
2913 queue);
2914 3200
2915 /* update queue timeout */ 3201
2916 reschedule_queue_timeout (queue); 3202static void
2917 /* prepare to continue with regular read task immediately */ 3203pending_reversal_timeout (void *cls)
2918 memmove (queue->cread_buf, 3204{
2919 &queue->cread_buf[INITIAL_KX_SIZE], 3205 struct sockaddr *in = cls;
2920 queue->cread_off - (INITIAL_KX_SIZE)); 3206 struct PendingReversal *pending_reversal;
2921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3207 struct GNUNET_HashCode key;
2922 "cread_off is %lu bytes before adjusting\n", 3208
2923 queue->cread_off); 3209 GNUNET_CRYPTO_hash (in,
2924 queue->cread_off -= INITIAL_KX_SIZE; 3210 sizeof(struct sockaddr),
2925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3211 &key);
2926 "cread_off set to %lu bytes\n", 3212 pending_reversal = GNUNET_CONTAINER_multihashmap_get (pending_reversals,
2927 queue->cread_off); 3213 &key);
2928 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); 3214
3215 GNUNET_assert (NULL != pending_reversal);
3216
3217 GNUNET_CONTAINER_multihashmap_remove (pending_reversals,
3218 &key,
3219 pending_reversal);
3220 GNUNET_free (pending_reversal->in);
3221 GNUNET_free (pending_reversal);
2929} 3222}
2930 3223
2931 3224
@@ -2950,17 +3243,18 @@ queue_read_kx (void *cls)
2950static int 3243static int
2951mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) 3244mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
2952{ 3245{
2953 struct Queue *queue;
2954 const char *path;
2955 struct sockaddr *in; 3246 struct sockaddr *in;
2956 socklen_t in_len = 0; 3247 socklen_t in_len = 0;
2957 struct GNUNET_NETWORK_Handle *sock; 3248 const char *path;
3249 struct sockaddr_in *v4;
3250 struct sockaddr_in6 *v6;
3251 unsigned int is_natd = GNUNET_NO;
3252 struct GNUNET_HashCode key;
2958 3253
2959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2960 "Connecting to %s\n", address); 3255 "Connecting to %s at %s\n",
2961 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, 3256 GNUNET_i2s (peer),
2962 "transport", 3257 address);
2963 "Connecting to %s\n", address);
2964 if (0 != strncmp (address, 3258 if (0 != strncmp (address,
2965 COMMUNICATOR_ADDRESS_PREFIX "-", 3259 COMMUNICATOR_ADDRESS_PREFIX "-",
2966 strlen (COMMUNICATOR_ADDRESS_PREFIX "-"))) 3260 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
@@ -2982,55 +3276,135 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
2982 "in %s\n", 3276 "in %s\n",
2983 GNUNET_a2s (in, in_len)); 3277 GNUNET_a2s (in, in_len));
2984 3278
2985 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); 3279 switch (in->sa_family)
2986 if (NULL == sock) 3280 {
3281 case AF_INET:
3282 v4 = (struct sockaddr_in *) in;
3283 if (0 == v4->sin_port){
3284 is_natd = GNUNET_YES;
3285 GNUNET_CRYPTO_hash (in,
3286 sizeof(struct sockaddr),
3287 &key);
3288 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (pending_reversals,
3289 &key))
3290 {
3291 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3292 "There is already a request reversal for `%s'at `%s'\n",
3293 GNUNET_i2s (peer),
3294 address);
3295 GNUNET_free (in);
3296 return GNUNET_SYSERR;
3297 }
3298 }
3299 break;
3300
3301 case AF_INET6:
3302 v6 = (struct sockaddr_in6 *) in;
3303 if (0 == v6->sin6_port)
3304 {
3305 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3306 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3307 GNUNET_i2s (peer),
3308 address);
3309 GNUNET_free (in);
3310 return GNUNET_SYSERR;
3311 }
3312 break;
3313
3314 default:
3315 GNUNET_assert (0);
3316 }
3317
3318 if (GNUNET_YES == is_natd)
2987 { 3319 {
2988 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3320 struct sockaddr_in local_sa;
2989 "socket(%d) failed: %s", 3321 struct PendingReversal *pending_reversal;
2990 in->sa_family, 3322
2991 strerror (errno)); 3323 memset (&local_sa, 0, sizeof(local_sa));
2992 GNUNET_free (in); 3324 local_sa.sin_family = AF_INET;
2993 return GNUNET_SYSERR; 3325 local_sa.sin_port = htons (bind_port);
3326 /* We leave sin_address at 0, let the kernel figure it out,
3327 even if our bind() is more specific. (May want to reconsider
3328 later.) */
3329 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3330 {
3331 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3332 "request reversal for `%s' at `%s' failed\n",
3333 GNUNET_i2s (peer),
3334 address);
3335 GNUNET_free (in);
3336 return GNUNET_SYSERR;
3337 }
3338 pending_reversal = GNUNET_new (struct PendingReversal);
3339 pending_reversal->in = in;
3340 GNUNET_assert (GNUNET_OK ==
3341 GNUNET_CONTAINER_multihashmap_put (pending_reversals,
3342 &key,
3343 pending_reversal,
3344 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3345 pending_reversal->target = *peer;
3346 pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT, &pending_reversal_timeout, in);
3347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3348 "Created NAT WAIT connection to `%s' at `%s'\n",
3349 GNUNET_i2s (peer),
3350 GNUNET_a2s (in, sizeof (struct sockaddr)));
2994 } 3351 }
2995 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) && 3352 else
2996 (errno != EINPROGRESS))
2997 { 3353 {
2998 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3354 struct GNUNET_NETWORK_Handle *sock;
2999 "connect to `%s' failed: %s", 3355 struct Queue *queue;
3000 address,
3001 strerror (errno));
3002 GNUNET_NETWORK_socket_close (sock);
3003 GNUNET_free (in);
3004 return GNUNET_SYSERR;
3005 }
3006 3356
3007 queue = GNUNET_new (struct Queue); 3357 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
3008 queue->target = *peer; 3358 if (NULL == sock)
3009 queue->address = in; 3359 {
3010 queue->address_len = in_len; 3360 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3011 queue->sock = sock; 3361 "socket(%d) failed: %s",
3012 queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND; 3362 in->sa_family,
3013 boot_queue (queue); 3363 strerror (errno));
3014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3364 GNUNET_free (in);
3015 "booted queue with target %s\n", 3365 return GNUNET_SYSERR;
3016 GNUNET_i2s (&queue->target)); 3366 }
3017 // queue->mq_awaits_continue = GNUNET_YES; 3367 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3018 queue->read_task = 3368 (errno != EINPROGRESS))
3019 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 3369 {
3020 queue->sock, 3370 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3021 &queue_read_kx, 3371 "connect to `%s' failed: %s",
3022 queue); 3372 address,
3373 strerror (errno));
3374 GNUNET_NETWORK_socket_close (sock);
3375 GNUNET_free (in);
3376 return GNUNET_SYSERR;
3377 }
3023 3378
3379 queue = GNUNET_new (struct Queue);
3380 queue->target = *peer;
3381 queue->address = in;
3382 queue->address_len = in_len;
3383 queue->sock = sock;
3384 queue->cs = GNUNET_TRANSPORT_CS_OUTBOUND;
3385 boot_queue (queue);
3386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3387 "booted queue with target %s\n",
3388 GNUNET_i2s (&queue->target));
3389 // queue->mq_awaits_continue = GNUNET_YES;
3390 queue->read_task =
3391 GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3392 queue->sock,
3393 &queue_read_kx,
3394 queue);
3024 3395
3025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3026 "start kx mq_init\n");
3027 3396
3028 start_initial_kx_out (queue); 3397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3029 queue->write_task = 3398 "start kx mq_init\n");
3030 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 3399
3031 queue->sock, 3400 start_initial_kx_out (queue);
3032 &queue_write, 3401 queue->write_task =
3033 queue); 3402 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
3403 queue->sock,
3404 &queue_write,
3405 queue);
3406 }
3407
3034 return GNUNET_OK; 3408 return GNUNET_OK;
3035} 3409}
3036 3410
@@ -3062,6 +3436,7 @@ get_lt_delete_it (void *cls,
3062 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lt->listen_sock)); 3436 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lt->listen_sock));
3063 lt->listen_sock = NULL; 3437 lt->listen_sock = NULL;
3064 } 3438 }
3439 GNUNET_free (lt);
3065 return GNUNET_OK; 3440 return GNUNET_OK;
3066} 3441}
3067 3442
@@ -3112,7 +3487,10 @@ do_shutdown (void *cls)
3112 GNUNET_NAT_unregister (nat); 3487 GNUNET_NAT_unregister (nat);
3113 nat = NULL; 3488 nat = NULL;
3114 } 3489 }
3490 GNUNET_CONTAINER_multihashmap_iterate (pending_reversals, &pending_reversals_delete_it, NULL);
3491 GNUNET_CONTAINER_multihashmap_destroy (pending_reversals);
3115 GNUNET_CONTAINER_multihashmap_iterate (lt_map, &get_lt_delete_it, NULL); 3492 GNUNET_CONTAINER_multihashmap_iterate (lt_map, &get_lt_delete_it, NULL);
3493 GNUNET_CONTAINER_multihashmap_destroy (lt_map);
3116 GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL); 3494 GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL);
3117 GNUNET_CONTAINER_multipeermap_destroy (queue_map); 3495 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
3118 if (NULL != ch) 3496 if (NULL != ch)
@@ -3454,7 +3832,7 @@ nat_register ()
3454 (const struct sockaddr **) saddrs, 3832 (const struct sockaddr **) saddrs,
3455 saddr_lens, 3833 saddr_lens,
3456 &nat_address_cb, 3834 &nat_address_cb,
3457 NULL /* FIXME: support reversal: #5529 */, 3835 try_connection_reversal,
3458 NULL /* closure */); 3836 NULL /* closure */);
3459 for (i = addrs_lens - 1; i >= 0; i--) 3837 for (i = addrs_lens - 1; i >= 0; i--)
3460 GNUNET_free (saddrs[i]); 3838 GNUNET_free (saddrs[i]);
@@ -3554,6 +3932,8 @@ run (void *cls,
3554 socklen_t addr_len_ipv6; 3932 socklen_t addr_len_ipv6;
3555 3933
3556 (void) cls; 3934 (void) cls;
3935
3936 pending_reversals = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
3557 memset (&v4,0,sizeof(struct sockaddr_in)); 3937 memset (&v4,0,sizeof(struct sockaddr_in));
3558 memset (&v6,0,sizeof(struct sockaddr_in6)); 3938 memset (&v6,0,sizeof(struct sockaddr_in6));
3559 cfg = c; 3939 cfg = c;
@@ -3647,6 +4027,7 @@ run (void *cls,
3647 GNUNET_TIME_UNIT_MINUTES, 4027 GNUNET_TIME_UNIT_MINUTES,
3648 &init_socket_resolv, 4028 &init_socket_resolv,
3649 &port); 4029 &port);
4030
3650 GNUNET_free (bindto); 4031 GNUNET_free (bindto);
3651 GNUNET_free (start); 4032 GNUNET_free (start);
3652} 4033}
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)
3735 NULL); 3735 NULL);
3736} 3736}
3737 3737
3738static void
3739try_connection_reversal (void *cls,
3740 const struct sockaddr *addr,
3741 socklen_t addrlen)
3742{
3743 /* FIXME: support reversal: #5529 */
3744}
3738 3745
3739/** 3746/**
3740 * Setup communicator and launch network interactions. 3747 * Setup communicator and launch network interactions.
@@ -3915,7 +3922,7 @@ run (void *cls,
3915 (const struct sockaddr **) &in, 3922 (const struct sockaddr **) &in,
3916 &in_len, 3923 &in_len,
3917 &nat_address_cb, 3924 &nat_address_cb,
3918 NULL /* FIXME: support reversal: #5529 */, 3925 try_connection_reversal,
3919 NULL /* closure */); 3926 NULL /* closure */);
3920} 3927}
3921 3928
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
800 /** 800 /**
801 * Size this msg had initially. This is needed to calculate the hmac at the target. 801 * Size this msg had initially. This is needed to calculate the hmac at the target.
802 * The header size can not be used for that, because the box size is getting smaller at each hop. 802 * The header size can not be used for that, because the box size is getting smaller at each hop.
803 */ 803 *
804 /**
805 * The length of the struct (in bytes, including the length field itself),
806 * in big-endian format.
807 */ 804 */
808 uint16_t orig_size GNUNET_PACKED; 805 uint16_t orig_size GNUNET_PACKED;
809 806
@@ -10383,9 +10380,10 @@ suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
10383 } 10380 }
10384 /* forward suggestion for queue creation to communicator */ 10381 /* forward suggestion for queue creation to communicator */
10385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 10382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10386 "Request #%u for `%s' communicator to create queue to `%s'\n", 10383 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
10387 (unsigned int) idgen, 10384 (unsigned int) idgen,
10388 prefix, 10385 prefix,
10386 GNUNET_i2s (pid),
10389 address); 10387 address);
10390 GNUNET_free (prefix); 10388 GNUNET_free (prefix);
10391 alen = strlen (address) + 1; 10389 alen = strlen (address) + 1;
@@ -10661,6 +10659,30 @@ start_dv_learn (void *cls)
10661 10659
10662 10660
10663/** 10661/**
10662 * Get the IP address without the port number.
10663 *
10664 * @param address The string contains a communicator prefix, IP address and port
10665 * like this 'tcp-92.68.150.1:55452'.
10666 * @return String with IP address only.
10667 */
10668static char *
10669get_address_without_port (const char *address)
10670{
10671 const char *colon;
10672 char *colon_rest;
10673 size_t colon_rest_length;
10674 char *address_without_port;
10675
10676 colon = strchr (address,':');
10677 colon_rest = GNUNET_strndup (address, colon - address);
10678 colon_rest_length = strlen (colon_rest);
10679 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
10680 GNUNET_free (colon_rest);
10681
10682 return address_without_port;
10683}
10684
10685/**
10664 * A new queue has been created, check if any address validation 10686 * A new queue has been created, check if any address validation
10665 * requests have been waiting for it. 10687 * requests have been waiting for it.
10666 * 10688 *
@@ -10676,16 +10698,31 @@ check_validation_request_pending (void *cls,
10676{ 10698{
10677 struct Queue *q = cls; 10699 struct Queue *q = cls;
10678 struct ValidationState *vs = value; 10700 struct ValidationState *vs = value;
10701 char *address_without_port_vs;
10702 char *address_without_port_q;
10703 int success = GNUNET_YES;
10679 10704
10705 address_without_port_vs = get_address_without_port (vs->address);
10706 address_without_port_q = get_address_without_port (q->address);
10707
10708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10709 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
10710 GNUNET_i2s (pid),
10711 address_without_port_vs,
10712 address_without_port_q);
10680 (void) pid; 10713 (void) pid;
10681 if ((GNUNET_YES == vs->awaiting_queue) && 10714 if ((GNUNET_YES == vs->awaiting_queue) &&
10682 (0 == strcmp (vs->address, q->address))) 10715 (0 == strcmp (address_without_port_vs, address_without_port_q)))
10683 { 10716 {
10717
10684 vs->awaiting_queue = GNUNET_NO; 10718 vs->awaiting_queue = GNUNET_NO;
10685 validation_transmit_on_queue (q, vs); 10719 validation_transmit_on_queue (q, vs);
10686 return GNUNET_NO; 10720 success = GNUNET_NO;
10687 } 10721 }
10688 return GNUNET_OK; 10722
10723 GNUNET_free (address_without_port_vs);
10724 GNUNET_free (address_without_port_q);
10725 return success;
10689} 10726}
10690 10727
10691 10728
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 @@
1M:1
2N:1
3X:1
4T:libgnunet_test_transport_plugin_cmd_nat_upnp
5K:1|{connect:{P:1:1:tcp_natted}}
6R:1|{tcp_port:0}|{udp_port:0}
7P: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 (
1048 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch; 1048 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch;
1049 1049
1050 send_del_address (ai); 1050 send_del_address (ai);
1051 if (NULL == ai->prev)
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "prev null\n");
1054 if (ch->ai_head == ai)
1055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1056 "equals head\n");
1057 if (NULL == ai->next)
1058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1059 "next null\n");
1060 if (ch->ai_tail == ai)
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1062 "equals tail\n");
1063 GNUNET_CONTAINER_DLL_remove (ch->ai_head, ch->ai_tail, ai); 1051 GNUNET_CONTAINER_DLL_remove (ch->ai_head, ch->ai_tail, ai);
1064 GNUNET_free (ai->address); 1052 GNUNET_free (ai->address);
1065 GNUNET_free (ai); 1053 GNUNET_free (ai);
1054 ai = NULL;
1066} 1055}
1067 1056
1068/** 1057/**
@@ -1074,9 +1063,13 @@ void
1074GNUNET_TRANSPORT_communicator_address_remove_all ( 1063GNUNET_TRANSPORT_communicator_address_remove_all (
1075 struct GNUNET_TRANSPORT_CommunicatorHandle *ch) 1064 struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
1076{ 1065{
1077 for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai; 1066 struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head;
1078 ai = ai->next) 1067 while (NULL != ai)
1068 {
1069 struct GNUNET_TRANSPORT_AddressIdentifier *ai_next = ai->next;
1079 GNUNET_TRANSPORT_communicator_address_remove (ai); 1070 GNUNET_TRANSPORT_communicator_address_remove (ai);
1071 ai = ai_next;
1072 }
1080} 1073}
1081 1074
1082 1075
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,
97 pos_prefix->address_prefix); 97 pos_prefix->address_prefix);
98 if (NULL != addr) 98 if (NULL != addr)
99 { 99 {
100 char *natted_p = strstr (pos_prefix->address_prefix, "_");
101
102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
103 "0 validating peer number %s %s %s\n",
104 natted_p,
105 pos_prefix->address_prefix,
106 addr);
100 if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp")) 107 if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp"))
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
102 "validating memcmp\n"); 109 "validating memcmp\n");
@@ -108,10 +115,28 @@ connect_peers_run (void *cls,
108 GNUNET_asprintf (&addr_and_port, 115 GNUNET_asprintf (&addr_and_port,
109 "%s:2086", 116 "%s:2086",
110 addr); 117 addr);
111 else 118 else if (NULL == natted_p)
112 GNUNET_asprintf (&addr_and_port, 119 GNUNET_asprintf (&addr_and_port,
113 "%s:60002", 120 "%s:60002",
114 addr); 121 addr);
122 else if (NULL != natted_p)
123 {
124 char *prefix;
125 char *rest;
126 char *rest2;
127 char *address;
128
129 prefix = strtok(addr, "_");
130 rest = strtok(NULL, "_");
131 rest2 = strtok(rest, "-");
132 address = strtok(NULL, "-");
133
134 GNUNET_asprintf (&addr_and_port,
135 "%s-%s:0",
136 prefix,
137 address);
138
139 }
115 peer = GNUNET_TESTING_get_peer (num, tl_system); 140 peer = GNUNET_TESTING_get_peer (num, tl_system);
116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
117 "validating peer number %u with identity %s and address %s %u %s\n", 142 "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,
244 "UNIXPATH", 244 "UNIXPATH",
245 udp_communicator_unix_path); 245 udp_communicator_unix_path);
246 246
247
247 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is, 248 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
248 sps->system_label); 249 sps->system_label);
249 GNUNET_TESTING_get_trait_test_system (system_cmd, 250 GNUNET_TESTING_get_trait_test_system (system_cmd,
@@ -384,11 +385,12 @@ start_peer_cleanup (void *cls)
384 GNUNET_free (sps->handlers); 385 GNUNET_free (sps->handlers);
385 sps->handlers = NULL; 386 sps->handlers = NULL;
386 } 387 }
387 if (NULL != sps->cfg) 388 //TODO Investigate why this caused problems during shutdown.
389 /*if (NULL != sps->cfg)
388 { 390 {
389 GNUNET_CONFIGURATION_destroy (sps->cfg); 391 GNUNET_CONFIGURATION_destroy (sps->cfg);
390 sps->cfg = NULL; 392 sps->cfg = NULL;
391 } 393 }*/
392 GNUNET_free (sps->cfgname); 394 GNUNET_free (sps->cfgname);
393 GNUNET_free (sps->node_ip); 395 GNUNET_free (sps->node_ip);
394 GNUNET_free (sps->system_label); 396 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
304GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, 304GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
305 struct GNUNET_MQ_Envelope *ev) 305 struct GNUNET_MQ_Envelope *ev)
306{ 306{
307 if (NULL == mq)
308 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
309 "mq is NUll when sending message of type %u\n",
310 (unsigned int) ntohs (ev->mh->type));
311 GNUNET_assert (NULL != mq); 307 GNUNET_assert (NULL != mq);
312 GNUNET_assert (NULL == ev->parent_queue); 308 GNUNET_assert (NULL == ev->parent_queue);
313 309