aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-communicator-udp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-01-30 03:32:20 +0100
committerChristian Grothoff <christian@grothoff.org>2019-01-30 03:32:20 +0100
commitea7d98e90d841200c2eb8cee31910b5bfa484880 (patch)
tree2549734c01c3f189957551101d746e322339528f /src/transport/gnunet-communicator-udp.c
parenta3dfb3954f1ae0ac7d0135af5e0562d71f25c036 (diff)
downloadgnunet-ea7d98e90d841200c2eb8cee31910b5bfa484880.tar.gz
gnunet-ea7d98e90d841200c2eb8cee31910b5bfa484880.zip
generate ACKs for backchannel
Diffstat (limited to 'src/transport/gnunet-communicator-udp.c')
-rw-r--r--src/transport/gnunet-communicator-udp.c309
1 files changed, 231 insertions, 78 deletions
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index 8265c4970..f307f6052 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -24,11 +24,7 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * TODO:
27 * - main sending logic 27 * - main BOXed sending logic
28 * - actual generation of ACKs (-> integrate with sending logic!)
29 * (specifically, ACKs should go as backchannel, let TNG
30 * decide how to send!)
31 * - handle ACKs from backchannel!
32 * - figure out what to do with MTU: 1280 for IPv6 is obvious; 28 * - figure out what to do with MTU: 1280 for IPv6 is obvious;
33 * what for IPv4? 1500? Also, consider differences in 29 * what for IPv4? 1500? Also, consider differences in
34 * headers for with/without box: need to give MIN of both 30 * headers for with/without box: need to give MIN of both
@@ -70,6 +66,36 @@
70#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES 66#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
71 67
72/** 68/**
69 * If we fall below this number of available KCNs,
70 * we generate additional ACKs until we reach
71 * #KCN_TARGET.
72 * Should be large enough that we don't generate ACKs all
73 * the time and still have enough time for the ACK to
74 * arrive before the sender runs out. So really this
75 * should ideally be based on the RTT.
76 */
77#define KCN_THRESHOLD 92
78
79/**
80 * How many KCNs do we keep around *after* we hit
81 * the #KCN_THRESHOLD? Should be larger than
82 * #KCN_THRESHOLD so we do not generate just one
83 * ACK at the time.
84 */
85#define KCN_TARGET 128
86
87/**
88 * What is the maximum delta between KCN sequence numbers
89 * that we allow. Used to expire 'ancient' KCNs that likely
90 * were dropped by the network. Must be larger than
91 * KCN_TARGET (otherwise we generate new KCNs all the time),
92 * but not too large (otherwise packet loss may cause
93 * sender to fall back to KX needlessly when sender runs
94 * out of ACK'ed KCNs due to losses).
95 */
96#define MAX_SQN_DELTA 160
97
98/**
73 * How often do we rekey based on number of bytes transmitted? 99 * How often do we rekey based on number of bytes transmitted?
74 * (additionally randomized). 100 * (additionally randomized).
75 */ 101 */
@@ -342,6 +368,11 @@ struct SharedSecret
342 * use this key? 368 * use this key?
343 */ 369 */
344 uint32_t sequence_allowed; 370 uint32_t sequence_allowed;
371
372 /**
373 * Number of active KCN entries.
374 */
375 unsigned int active_kce_count;
345}; 376};
346 377
347 378
@@ -581,6 +612,7 @@ kce_destroy (struct KeyCacheEntry *kce)
581{ 612{
582 struct SharedSecret *ss = kce->ss; 613 struct SharedSecret *ss = kce->ss;
583 614
615 ss->active_kce_count--;
584 GNUNET_CONTAINER_DLL_remove (ss->kce_head, 616 GNUNET_CONTAINER_DLL_remove (ss->kce_head,
585 ss->kce_tail, 617 ss->kce_tail,
586 kce); 618 kce);
@@ -642,6 +674,7 @@ kce_generate (struct SharedSecret *ss,
642 GNUNET_CONTAINER_DLL_insert (ss->kce_head, 674 GNUNET_CONTAINER_DLL_insert (ss->kce_head,
643 ss->kce_tail, 675 ss->kce_tail,
644 kce); 676 kce);
677 ss->active_kce_count++;
645 (void) GNUNET_CONTAINER_multishortmap_put (key_cache, 678 (void) GNUNET_CONTAINER_multishortmap_put (key_cache,
646 &kce->kid, 679 &kce->kid,
647 kce, 680 kce,
@@ -1048,7 +1081,52 @@ setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
1048 GNUNET_NO); 1081 GNUNET_NO);
1049 return ss; 1082 return ss;
1050} 1083}
1051 1084
1085
1086/**
1087 * We received an ACK for @a pid. Check if it is for
1088 * the receiver in @a value and if so, handle it and
1089 * return #GNUNET_NO. Otherwise, return #GNUNET_YES.
1090 *
1091 * @param cls a `const struct UDPAck`
1092 * @param pid peer the ACK is from
1093 * @param value a `struct ReceiverAddress`
1094 * @return #GNUNET_YES to continue to iterate
1095 */
1096static int
1097handle_ack (void *cls,
1098 const struct GNUNET_PeerIdentity *pid,
1099 void *value)
1100{
1101 const struct UDPAck *ack = cls;
1102 struct ReceiverAddress *receiver = value;
1103
1104 (void) pid;
1105 for (struct SharedSecret *ss = receiver->ss_head;
1106 NULL != ss;
1107 ss = ss->next)
1108 {
1109 if (0 == memcmp (&ack->cmac,
1110 &ss->cmac,
1111 sizeof (struct GNUNET_HashCode)))
1112 {
1113 ss->sequence_allowed = GNUNET_MAX (ss->sequence_allowed,
1114 ntohl (ack->sequence_max));
1115 /* move ss to head to avoid discarding it anytime soon! */
1116 GNUNET_CONTAINER_DLL_remove (sender->ss_head,
1117 sender->ss_tail,
1118 ss);
1119 GNUNET_CONTAINER_DLL_insert (sender->ss_head,
1120 sender->ss_tail,
1121 ss);
1122 /* FIXME: if this changed sequence_allowed,
1123 update MTU / MQ of 'receiver'! */
1124 return GNUNET_NO;
1125 }
1126 }
1127 return GNUNET_YES;
1128}
1129
1052 1130
1053/** 1131/**
1054 * Test if we have received a valid message in plaintext. 1132 * Test if we have received a valid message in plaintext.
@@ -1078,26 +1156,10 @@ try_handle_plaintext (struct SenderAddress *sender,
1078 { 1156 {
1079 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK: 1157 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
1080 /* lookup master secret by 'cmac', then update sequence_max */ 1158 /* lookup master secret by 'cmac', then update sequence_max */
1081 for (struct SharedSecret *ss = sender->ss_head; 1159 GNUNET_CONTAINER_multihashmap_get_multiple (receivers,
1082 NULL != ss; 1160 &sender->target,
1083 ss = ss->next) 1161 &handle_ack,
1084 { 1162 (void *) ack);
1085 if (0 == memcmp (&ack->cmac,
1086 &ss->cmac,
1087 sizeof (ss->cmac)))
1088 {
1089 ss->sequence_allowed = GNUNET_MAX (ss->sequence_allowed,
1090 ntohl (ack->sequence_max));
1091 /* move ss to head to avoid discarding it anytime soon! */
1092 GNUNET_CONTAINER_DLL_remove (sender->ss_head,
1093 sender->ss_tail,
1094 ss);
1095 GNUNET_CONTAINER_DLL_insert (sender->ss_head,
1096 sender->ss_tail,
1097 ss);
1098 break;
1099 }
1100 }
1101 /* There could be more messages after the ACK, handle those as well */ 1163 /* There could be more messages after the ACK, handle those as well */
1102 buf += ntohs (hdr->size); 1164 buf += ntohs (hdr->size);
1103 buf_size -= ntohs (hdr->size); 1165 buf_size -= ntohs (hdr->size);
@@ -1105,6 +1167,9 @@ try_handle_plaintext (struct SenderAddress *sender,
1105 buf, 1167 buf,
1106 buf_size); 1168 buf_size);
1107 break; 1169 break;
1170 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD:
1171 /* skip padding */
1172 break;
1108 default: 1173 default:
1109 pass_plaintext_to_core (sender, 1174 pass_plaintext_to_core (sender,
1110 buf, 1175 buf,
@@ -1118,15 +1183,33 @@ try_handle_plaintext (struct SenderAddress *sender,
1118 * the sender an `struct UDPAck` at the next opportunity to allow the 1183 * the sender an `struct UDPAck` at the next opportunity to allow the
1119 * sender to use @a ss longer (assuming we did not yet already 1184 * sender to use @a ss longer (assuming we did not yet already
1120 * recently). 1185 * recently).
1186 *
1187 * @param ss shared secret to generate ACKs for
1121 */ 1188 */
1122static void 1189static void
1123consider_ss_ack (struct SharedSecret *ss) 1190consider_ss_ack (struct SharedSecret *ss)
1124{ 1191{
1125 GNUNET_assert (NULL != ss->sender); 1192 GNUNET_assert (NULL != ss->sender);
1126 for (uint32_t i=1;i<0 /* FIXME: ack-based! */;i++) 1193 /* drop ancient KeyCacheEntries */
1127 kce_generate (ss, 1194 while ( (NULL != ss->kce_head) &&
1128 i); 1195 (MAX_SQN_DELTA < ss->kce_head->sequence_number - ss->kce_tail->sequence_number) )
1129 // FIXME: consider generating ACK and more KCEs for ss! 1196 kce_destroy (ss->kce_tail);
1197 if (ss->active_kce_count < KCN_THRESHOLD)
1198 {
1199 struct UDPAck ack;
1200
1201 while (ss->active_kce_count < KCN_TARGET)
1202 kce_generate (ss,
1203 ++ss->sequence_used);
1204 ack.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK);
1205 ack.header.size = htons (sizeof (ack));
1206 ack.sequence_max = htonl (ss->sequence_max);
1207 ack.cmac = ss->cmac;
1208 GNUNET_TRANSPORT_communicator_notify (ch,
1209 &ss->sender->target,
1210 COMMUNICATOR_ADDRESS_PREFIX,
1211 &ack.header);
1212 }
1130} 1213}
1131 1214
1132 1215
@@ -1392,8 +1475,8 @@ sock_read (void *cls)
1392 1, 1475 1,
1393 GNUNET_NO); 1476 GNUNET_NO);
1394 GNUNET_STATISTICS_update (stats, 1477 GNUNET_STATISTICS_update (stats,
1395 "# bytes decrypted without BOX", 1478 "# messages decrypted without BOX",
1396 sizeof (pbuf) - sizeof (*uc), 1479 1,
1397 GNUNET_NO); 1480 GNUNET_NO);
1398 try_handle_plaintext (sender, 1481 try_handle_plaintext (sender,
1399 &uc[1], 1482 &uc[1],
@@ -1557,45 +1640,106 @@ mq_send (struct GNUNET_MQ_Handle *mq,
1557{ 1640{
1558 struct ReceiverAddress *receiver = impl_state; 1641 struct ReceiverAddress *receiver = impl_state;
1559 uint16_t msize = ntohs (msg->size); 1642 uint16_t msize = ntohs (msg->size);
1560 ssize_t sent;
1561 1643
1562 GNUNET_assert (mq == receiver->mq); 1644 GNUNET_assert (mq == receiver->mq);
1563 // FIXME: pick encryption method, encrypt and transmit!! 1645 if (msize > receiver->mtu)
1564
1565#if 0
1566 /* compute 'tc' and append in encrypted format to cwrite_buf */
1567 tc.sender = my_identity;
1568 tc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1569 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE);
1570 ths.purpose.size = htonl (sizeof (ths));
1571 ths.sender = my_identity;
1572 ths.receiver = queue->target;
1573 ths.ephemeral = *epub;
1574 ths.monotonic_time = tc.monotonic_time;
1575 GNUNET_assert (GNUNET_OK ==
1576 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1577 &ths.purpose,
1578 &tc.sender_sig));
1579 GNUNET_assert (0 ==
1580 gcry_cipher_encrypt (queue->out_cipher,
1581 &queue->cwrite_buf[queue->cwrite_off],
1582 sizeof (tc),
1583 &tc,
1584 sizeof (tc)));
1585
1586 sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1587 ...);
1588 GNUNET_MQ_impl_send_continue (mq);
1589 if (-1 == sent)
1590 { 1646 {
1591 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 1647 GNUNET_break (0);
1592 "send"); 1648 receiver_destroy (receiver);
1593 return; 1649 return;
1594 } 1650 }
1651
1652 // FIXME: add support for BOX encryption method!
1595 1653
1596#endif 1654 /* KX encryption method */
1597 1655 {
1656 struct UdpHandshakeSignature uhs;
1657 struct UdpConfirmation uc;
1658 struct InitialKX kx;
1659 struct GNUNET_CRYPTO_EcdhePrivateKey epriv;
1660 char dgram[receiver->mtu +
1661 sizeof (uc) +
1662 sizeof (kx)];
1663 size_t dpos;
1664
1665 GNUNET_assert (GNUNET_OK ==
1666 GNUNET_CRYPTO_ecdhe_key_create2 (&epriv));
1667 /* compute 'uc' */
1668 uc.sender = my_identity;
1669 uc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1670 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE);
1671 uhs.purpose.size = htonl (sizeof (uhs));
1672 uhs.sender = my_identity;
1673 uhs.receiver = receiver->target;
1674 GNUNET_CRYPTO_ecdhe_key_get_public (&epriv,
1675 &uhs.ephemeral);
1676 uhs.monotonic_time = uc.monotonic_time;
1677 GNUNET_assert (GNUNET_OK ==
1678 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1679 &uhs.purpose,
1680 &uc.sender_sig));
1681 /* Leave space for kx */
1682 dpos = sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
1683 /* Append encrypted uc to dgram */
1684 GNUNET_assert (0 ==
1685 gcry_cipher_encrypt (out_cipher,
1686 &dgram[dpos],
1687 sizeof (uc),
1688 &uc,
1689 sizeof (uc)));
1690 dpos += sizeof (uc);
1691 /* Append encrypted payload to dgram */
1692 GNUNET_assert (0 ==
1693 gcry_cipher_encrypt (out_cipher,
1694 &dgram[dpos],
1695 msize,
1696 msg,
1697 msize));
1698 dpos += msize;
1699 /* Pad to MTU */
1700 {
1701 char pad[sizeof (dgram) - pos];
1598 1702
1703 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
1704 pad,
1705 sizeof (pad));
1706 if (sizeof (pad) > sizeof (struct GNUNET_MessageHeader))
1707 {
1708 struct GNUNET_MessageHeader hdr = {
1709 .size = htons (sizeof (pad)),
1710 .type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD)
1711 };
1712
1713 memcpy (pad,
1714 &hdr,
1715 sizeof (hdr));
1716 GNUNET_assert (0 ==
1717 gcry_cipher_encrypt (out_cipher,
1718 &dgram[dpos],
1719 sizeof (pad),
1720 pad,
1721 sizeof (pad)));
1722 }
1723 }
1724 /* Datagram starts with kx */
1725 kx.ephemeral = uhs.ephemeral;
1726 GNUNET_assert (0 ==
1727 gcry_cipher_gettag (out_cipher,
1728 kx.gcm_tag,
1729 sizeof (kx.gcm_tag)));
1730 memcpy (dgram,
1731 &kx,
1732 sizeof (kx));
1733 if (-1 ==
1734 GNUNET_NETWORK_socket_sendto (udp_sock,
1735 dgram,
1736 sizeof (dgram),
1737 receiver->address,
1738 receiver->address_len))
1739 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1740 "send");
1741 GNUNET_MQ_impl_send_continue (mq);
1742 } /* End of KX encryption method */
1599} 1743}
1600 1744
1601 1745
@@ -1697,6 +1841,7 @@ receiver_setup (const struct GNUNET_PeerIdentity *target,
1697 NULL, 1841 NULL,
1698 &mq_error, 1842 &mq_error,
1699 receiver); 1843 receiver);
1844 receiver->mtu = 1200 /* FIXME: MTU OK? */;
1700 if (NULL == timeout_task) 1845 if (NULL == timeout_task)
1701 timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, 1846 timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts,
1702 NULL); 1847 NULL);
@@ -1726,14 +1871,14 @@ receiver_setup (const struct GNUNET_PeerIdentity *target,
1726 default: 1871 default:
1727 GNUNET_assert (0); 1872 GNUNET_assert (0);
1728 } 1873 }
1729 queue->qh 1874 receiver->qh
1730 = GNUNET_TRANSPORT_communicator_mq_add (ch, 1875 = GNUNET_TRANSPORT_communicator_mq_add (ch,
1731 &receiver->target, 1876 &receiver->target,
1732 foreign_addr, 1877 foreign_addr,
1733 1200 /* FIXME: MTU OK? */, 1878 receiver->mtu,
1734 queue->nt, 1879 receiver->nt,
1735 GNUNET_TRANSPORT_CS_OUTBOUND, 1880 GNUNET_TRANSPORT_CS_OUTBOUND,
1736 queue->mq); 1881 receiver->mq);
1737 GNUNET_free (foreign_addr); 1882 GNUNET_free (foreign_addr);
1738 } 1883 }
1739} 1884}
@@ -1887,13 +2032,11 @@ do_shutdown (void *cls)
1887 2032
1888 2033
1889/** 2034/**
1890 * Function called when the transport service has received an 2035 * Function called when the transport service has received a
1891 * acknowledgement for this communicator (!) via a different return 2036 * backchannel message for this communicator (!) via a different return
1892 * path. 2037 * path. Should be an acknowledgement.
1893 *
1894 * Not applicable for UDP.
1895 * 2038 *
1896 * @param cls closure 2039 * @param cls closure, NULL
1897 * @param sender which peer sent the notification 2040 * @param sender which peer sent the notification
1898 * @param msg payload 2041 * @param msg payload
1899 */ 2042 */
@@ -1902,10 +2045,20 @@ enc_notify_cb (void *cls,
1902 const struct GNUNET_PeerIdentity *sender, 2045 const struct GNUNET_PeerIdentity *sender,
1903 const struct GNUNET_MessageHeader *msg) 2046 const struct GNUNET_MessageHeader *msg)
1904{ 2047{
2048 const struct UDPAck *ack;
2049
1905 (void) cls; 2050 (void) cls;
1906 (void) sender; 2051 if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
1907 (void) msg; 2052 (ntohs (msg->size) != sizeof (struct UDPAck)) )
1908 GNUNET_break_op (0); 2053 {
2054 GNUNET_break_op (0);
2055 return;
2056 }
2057 ack = (const struct UDPAck *) msg;
2058 GNUNET_CONTAINER_multihashmap_get_multiple (receivers,
2059 sender,
2060 &handle_ack,
2061 (void *) ack);
1909} 2062}
1910 2063
1911 2064