aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2023-01-27 13:07:48 +0100
committert3sserakt <t3ss@posteo.de>2023-01-27 13:07:48 +0100
commit1a95d92b448b1dc77332781507cb6155b46c45b0 (patch)
tree1325457b90077904c91e37c4eeef8314df1a8a53
parenta21cb18203056306fa08ecbcaf4100a6c94cc4d9 (diff)
downloadgnunet-1a95d92b448b1dc77332781507cb6155b46c45b0.tar.gz
gnunet-1a95d92b448b1dc77332781507cb6155b46c45b0.zip
TNG: Added nat reversal code to tcp communicator. Prepared udp communicator.
-rw-r--r--src/transport/gnunet-communicator-tcp.c729
-rw-r--r--src/transport/gnunet-communicator-udp.c9
2 files changed, 563 insertions, 175 deletions
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